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.refraction;
18  
19  import org.hipparchus.analysis.interpolation.BilinearInterpolatingFunction;
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.orekit.rugged.errors.RuggedException;
22  import org.orekit.rugged.errors.RuggedMessages;
23  import org.orekit.rugged.intersection.IntersectionAlgorithm;
24  import org.orekit.rugged.linesensor.LineSensor;
25  import org.orekit.rugged.linesensor.SensorPixel;
26  import org.orekit.rugged.utils.NormalizedGeodeticPoint;
27  
28  /**
29   * Base class for atmospheric refraction model.
30   * @author Sergio Esteves
31   * @author Guylaine Prat
32   * @since 2.0
33   */
34  public abstract class AtmosphericRefraction {
35  
36      /** Flag to tell if we must compute the correction.
37       * By default: computation is set up.
38       * @since 2.1
39       */
40      private boolean mustBeComputed;
41  
42      /** The current atmospheric parameters.
43       * @since 2.1
44       */
45      private AtmosphericComputationParameters atmosphericParams;
46  
47      /** Bilinear interpolating function for pixel (used by inverse location).
48       * @since 2.1
49      */
50      private BilinearInterpolatingFunction bifPixel;
51  
52      /** Bilinear interpolating function of line (used by inverse location).
53       * @since 2.1
54      */
55      private BilinearInterpolatingFunction bifLine;
56  
57      /**
58       * Default constructor.
59       */
60      protected AtmosphericRefraction() {
61          // Set up the atmospheric parameters ... with lazy evaluation of the grid (done only if necessary)
62          this.atmosphericParams = new AtmosphericComputationParameters();
63          this.mustBeComputed    = true;
64          this.bifPixel          = null;
65          this.bifLine           = null;
66      }
67  
68      /** Apply correction to the intersected point with an atmospheric refraction model.
69       * @param satPos satellite position, in <em>body frame</em>
70       * @param satLos satellite line of sight, in <em>body frame</em>
71       * @param rawIntersection intersection point before refraction correction
72       * @param algorithm intersection algorithm
73       * @return corrected point with the effect of atmospheric refraction
74       * {@link org.orekit.rugged.utils.ExtendedEllipsoid#pointAtAltitude(Vector3D, Vector3D, double)} or see
75       * {@link org.orekit.rugged.intersection.IntersectionAlgorithm#refineIntersection(org.orekit.rugged.utils.ExtendedEllipsoid, Vector3D, Vector3D, NormalizedGeodeticPoint)}
76       */
77      public abstract NormalizedGeodeticPointnt.html#NormalizedGeodeticPoint">NormalizedGeodeticPoint applyCorrection(Vector3D satPos, Vector3D satLos, NormalizedGeodeticPoint rawIntersection,
78                                              IntersectionAlgorithm algorithm);
79  
80      /** Deactivate computation (needed for the inverse location computation).
81       * @since 2.1
82       */
83      public void deactivateComputation() {
84          this.mustBeComputed = false;
85      }
86  
87      /** Reactivate computation (needed for the inverse location computation).
88       * @since 2.1
89       */
90      public void reactivateComputation() {
91          this.mustBeComputed = true;
92      }
93  
94      /** Tell if the computation must be performed.
95       * @return true if computation must be performed; false otherwise
96       * @since 2.1
97       */
98      public boolean mustBeComputed() {
99          return mustBeComputed;
100     }
101 
102     /** Configuration of the interpolation grid. This grid is associated to the given sensor,
103      * with the given min and max lines.
104      * @param sensor line sensor
105      * @param minLine min line defined for the inverse location
106      * @param maxLine max line defined for the inverse location
107      * @since 2.1
108      */
109     public void configureCorrectionGrid(final LineSensor sensor, final int minLine, final int maxLine) {
110 
111         atmosphericParams.configureCorrectionGrid(sensor, minLine, maxLine);
112     }
113 
114    /** Check if the current atmospheric parameters are the same as the asked ones.
115     * @param sensorName the asked sensor name
116     * @param minLine the asked min line
117     * @param maxLine the asked max line
118     * @return true if same context; false otherwise
119     * @since 2.1
120     */
121     public Boolean isSameContext(final String sensorName, final int minLine, final int maxLine) {
122 
123         return (Double.compare(atmosphericParams.getMinLineSensor(), minLine) == 0) &&
124                (Double.compare(atmosphericParams.getMaxLineSensor(), maxLine) == 0) &&
125                (atmosphericParams.getSensorName().compareTo(sensorName) == 0);
126     }
127 
128     /** Get the computation parameters.
129      * @return the AtmosphericComputationParameters
130      * @since 2.1
131      */
132     public AtmosphericComputationParameters getComputationParameters() {
133         return atmosphericParams;
134     }
135 
136     /** Set the grid steps in pixel and line (used to compute inverse location).
137      * Overwrite the default values, for time optimization for instance.
138      * @param pixelStep pixel step for the inverse location computation
139      * @param lineStep line step for the inverse location computation
140      * @since 2.1
141      */
142     public void setGridSteps(final int pixelStep, final int lineStep) {
143         atmosphericParams.setGridSteps(pixelStep, lineStep);
144     }
145 
146     /** Compute the correction functions for pixel and lines.
147      * The corrections are computed for pixels and lines, on a regular grid at sensor level.
148      * The corrections are based on the difference on grid nodes (where direct loc is known with atmosphere refraction)
149      * and the sensor pixel found by inverse loc without atmosphere refraction.
150      * The bilinear interpolating functions are then computed for pixel and for line.
151      * Need to be computed only once for a given sensor with the same minLine and maxLine.
152      * @param sensorPixelGridInverseWithout inverse location grid WITHOUT atmospheric refraction
153      * @since 2.1
154      */
155     public void computeGridCorrectionFunctions(final SensorPixel[][] sensorPixelGridInverseWithout) {
156 
157         final int nbPixelGrid = atmosphericParams.getNbPixelGrid();
158         final int nbLineGrid = atmosphericParams.getNbLineGrid();
159         final double[] pixelGrid = atmosphericParams.getUgrid();
160         final double[] lineGrid = atmosphericParams.getVgrid();
161 
162         // Initialize the needed diff functions
163         final double[][] gridDiffPixel = new double[nbPixelGrid][nbLineGrid];
164         final double[][] gridDiffLine = new double[nbPixelGrid][nbLineGrid];
165 
166         // Compute the difference between grids nodes WITH - without atmosphere
167         for (int lineIndex = 0; lineIndex < nbLineGrid; lineIndex++) {
168             for (int pixelIndex = 0; pixelIndex < nbPixelGrid; pixelIndex++) {
169 
170                 if (sensorPixelGridInverseWithout[pixelIndex][lineIndex] != null) {
171                     final double diffLine = lineGrid[lineIndex] - sensorPixelGridInverseWithout[pixelIndex][lineIndex].getLineNumber();
172                     final double diffPixel = pixelGrid[pixelIndex] - sensorPixelGridInverseWithout[pixelIndex][lineIndex].getPixelNumber();
173                     gridDiffPixel[pixelIndex][lineIndex] = diffPixel;
174                     gridDiffLine[pixelIndex][lineIndex] = diffLine;
175 
176                 } else {
177                     // Impossible to find the point in the given min line and max line
178                     throw new RuggedException(RuggedMessages.INVALID_RANGE_FOR_LINES,
179                                               atmosphericParams.getMinLineSensor(), atmosphericParams.getMaxLineSensor(), "");
180                 }
181             }
182         }
183         // Definition of the interpolating function for pixel and for line
184         this.bifPixel = new BilinearInterpolatingFunction(pixelGrid, lineGrid, gridDiffPixel);
185         this.bifLine = new BilinearInterpolatingFunction(pixelGrid, lineGrid, gridDiffLine);
186     }
187 
188     /**
189      * @return the bilinear interpolating function for pixel correction
190      */
191     public BilinearInterpolatingFunction getBifPixel() {
192         return bifPixel;
193     }
194 
195     /**
196      * @return the bilinear interpolating function for line correction
197      */
198     public BilinearInterpolatingFunction getBifLine() {
199         return bifLine;
200     }
201 }