GridCell.java

  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. /** Holder for one cell of grid data surrounding one point.
  19.  * @author Luc Maisonobe
  20.  * @since 13.0
  21.  */
  22. class GridCell {

  23.     /** Latitude difference with respect to South cell edge. */
  24.     private final double deltaSouth;

  25.     /** Longitude difference with respect to West cell edge. */
  26.     private final double deltaWest;

  27.     /** Cell size in latitude. */
  28.     private final double sizeLat;

  29.     /** Cell size in longitude. */
  30.     private final double sizeLon;

  31.     /** North-West value. */
  32.     private final double nw;

  33.     /** South-West value. */
  34.     private final double sw;

  35.     /** South-East value. */
  36.     private final double se;

  37.     /** North-East value. */
  38.     private final double ne;

  39.     /**
  40.      * Build a grid cell from corner data.
  41.      *
  42.      * @param deltaSouth point latitude minus South cell edge latitude
  43.      * @param deltaWest  point longitude minus West cell edge longitude
  44.      * @param sizeLat    cell size in latitude
  45.      * @param sizeLon    cell size in longitude
  46.      * @param nw         North-West value
  47.      * @param sw         South-West value
  48.      * @param se         South-East value
  49.      * @param ne         North-East value
  50.      */
  51.     GridCell(final double deltaSouth, final double deltaWest, final double sizeLat, final double sizeLon,
  52.              final double nw, final double sw, final double se, final double ne) {
  53.         this.deltaSouth = deltaSouth;
  54.         this.deltaWest  = deltaWest;
  55.         this.sizeLat    = sizeLat;
  56.         this.sizeLon    = sizeLon;
  57.         this.nw         = nw;
  58.         this.sw         = sw;
  59.         this.se         = se;
  60.         this.ne         = ne;
  61.     }

  62.     /** Build a grid cell by applying a function to two existing cells.
  63.      * <p>
  64.      * The cells are expected to be consistent (i.e. same locations,
  65.      * same sizes), but no verification is done here. It works in
  66.      * the context of ITR-R P.834 because the grids have similar
  67.      * samplings, it would not work fro general and inconsistent grids.
  68.      * </p>
  69.      * @param function function to apply to all cells corners
  70.      * @param cell1 first cell
  71.      * @param cell2 second cell
  72.      */
  73.     GridCell(final BiFunction function,
  74.              final GridCell cell1, final GridCell cell2) {
  75.         this.deltaSouth = cell1.deltaSouth;
  76.         this.deltaWest  = cell1.deltaWest;
  77.         this.sizeLat    = cell1.sizeLat;
  78.         this.sizeLon    = cell1.sizeLon;
  79.         this.nw         = function.apply(cell1.nw, cell2.nw);
  80.         this.sw         = function.apply(cell1.sw, cell2.sw);
  81.         this.se         = function.apply(cell1.se, cell2.se);
  82.         this.ne         = function.apply(cell1.ne, cell2.ne);
  83.     }

  84.     /** Build a grid cell by applying a function to three existing cells.
  85.      * <p>
  86.      * The cells are expected to be consistent (i.e. same locations,
  87.      * same sizes), but no verification is done here. It works in
  88.      * the context of ITR-R P.834 because the grids have similar
  89.      * samplings, it would not work fro general and inconsistent grids.
  90.      * </p>
  91.      * @param function function to apply to all cells corners
  92.      * @param cell1 first cell
  93.      * @param cell2 second cell
  94.      * @param cell3 third cell
  95.      */
  96.     GridCell(final TriFunction function,
  97.              final GridCell cell1, final GridCell cell2, final GridCell cell3) {
  98.         this.deltaSouth = cell1.deltaSouth;
  99.         this.deltaWest  = cell1.deltaWest;
  100.         this.sizeLat    = cell1.sizeLat;
  101.         this.sizeLon    = cell1.sizeLon;
  102.         this.nw         = function.apply(cell1.nw, cell2.nw, cell3.nw);
  103.         this.sw         = function.apply(cell1.sw, cell2.sw, cell3.sw);
  104.         this.se         = function.apply(cell1.se, cell2.se, cell3.se);
  105.         this.ne         = function.apply(cell1.ne, cell2.ne, cell3.ne);
  106.     }

  107.     /** Build a grid cell by applying a function to four existing cells.
  108.      * <p>
  109.      * The cells are expected to be consistent (i.e. same locations,
  110.      * same sizes), but no verification is done here. It works in
  111.      * the context of ITR-R P.834 because the grids have similar
  112.      * samplings, it would not work fro general and inconsistent grids.
  113.      * </p>
  114.      * @param function function to apply to all cells corners
  115.      * @param cell1 first cell
  116.      * @param cell2 second cell
  117.      * @param cell3 third cell
  118.      * @param cell4 fourth cell
  119.      */
  120.     GridCell(final QuarticFunction function,
  121.              final GridCell cell1, final GridCell cell2,
  122.              final GridCell cell3, final GridCell cell4) {
  123.         this.deltaSouth = cell1.deltaSouth;
  124.         this.deltaWest  = cell1.deltaWest;
  125.         this.sizeLat    = cell1.sizeLat;
  126.         this.sizeLon    = cell1.sizeLon;
  127.         this.nw         = function.apply(cell1.nw, cell2.nw, cell3.nw, cell4.nw);
  128.         this.sw         = function.apply(cell1.sw, cell2.sw, cell3.sw, cell4.sw);
  129.         this.se         = function.apply(cell1.se, cell2.se, cell3.se, cell4.se);
  130.         this.ne         = function.apply(cell1.ne, cell2.ne, cell3.ne, cell4.ne);
  131.     }

  132.     /** Build a grid cell by applying a function to five existing cells.
  133.      * <p>
  134.      * The cells are expected to be consistent (i.e. same locations,
  135.      * same sizes), but no verification is done here. It works in
  136.      * the context of ITR-R P.834 because the grids have similar
  137.      * samplings, it would not work fro general and inconsistent grids.
  138.      * </p>
  139.      * @param function function to apply to all cells corners
  140.      * @param cell1 first cell
  141.      * @param cell2 second cell
  142.      * @param cell3 third cell
  143.      * @param cell4 fourth cell
  144.      * @param cell5 fifth cell
  145.      */
  146.     GridCell(final QuinticFunction function,
  147.              final GridCell cell1, final GridCell cell2, final GridCell cell3,
  148.              final GridCell cell4, final GridCell cell5) {
  149.         this.deltaSouth = cell1.deltaSouth;
  150.         this.deltaWest  = cell1.deltaWest;
  151.         this.sizeLat    = cell1.sizeLat;
  152.         this.sizeLon    = cell1.sizeLon;
  153.         this.nw         = function.apply(cell1.nw, cell2.nw, cell3.nw, cell4.nw, cell5.nw);
  154.         this.sw         = function.apply(cell1.sw, cell2.sw, cell3.sw, cell4.sw, cell5.sw);
  155.         this.se         = function.apply(cell1.se, cell2.se, cell3.se, cell4.se, cell5.se);
  156.         this.ne         = function.apply(cell1.ne, cell2.ne, cell3.ne, cell4.ne, cell5.ne);
  157.     }

  158.     /** Evaluate cell value at point location using bi-linear interpolation.
  159.      * @return cell value at point location
  160.      */
  161.     public double evaluate() {
  162.         final double deltaNorth = sizeLat - deltaSouth;
  163.         final double deltaEast  = sizeLon - deltaWest;
  164.         return (deltaSouth * (deltaWest * ne + deltaEast * nw) +
  165.                 deltaNorth * (deltaWest * se + deltaEast * sw)) /
  166.                (sizeLat * sizeLon);
  167.     }

  168.     /** Interface for function that can be applied to the corners of two cells. */
  169.     @FunctionalInterface
  170.     public interface BiFunction {
  171.         /** Apply function to similar corners coming from two cells.
  172.          * @param corner1 value at corner of first cell
  173.          * @param corner2 value at corner of second cell
  174.          * @return function evaluated at similar corners of two cells
  175.          */
  176.         double apply(double corner1, double corner2);
  177.     }

  178.     /** Interface for function that can be applied to the corners of three cells. */
  179.     @FunctionalInterface
  180.     public interface TriFunction {
  181.         /** Apply function to similar corners coming from three cells.
  182.          * @param corner1 value at corner of first cell
  183.          * @param corner2 value at corner of second cell
  184.          * @param corner3 value at corner of third cell
  185.          * @return function evaluated at similar corners of three cells
  186.          */
  187.         double apply(double corner1, double corner2, double corner3);
  188.     }

  189.     /** Interface for function that can be applied to the corners of four cells. */
  190.     @FunctionalInterface
  191.     public interface QuarticFunction {
  192.         /** Apply function to similar corners coming from four cells.
  193.          * @param corner1 value at corner of first cell
  194.          * @param corner2 value at corner of second cell
  195.          * @param corner3 value at corner of third cell
  196.          * @param corner4 value at corner of fourth cell
  197.          * @return function evaluated at similar corners of four cells
  198.          */
  199.         double apply(double corner1, double corner2, double corner3, double corner4);
  200.     }

  201.     /** Interface for function that can be applied to the corners of five cells. */
  202.     @FunctionalInterface
  203.     public interface QuinticFunction {
  204.         /** Apply function to similar corners coming from five cells.
  205.          * @param corner1 value at corner of first cell
  206.          * @param corner2 value at corner of second cell
  207.          * @param corner3 value at corner of third cell
  208.          * @param corner4 value at corner of fourth cell
  209.          * @param corner5 value at corner of fifth cell
  210.          * @return function evaluated at similar corners of five cells
  211.          */
  212.         double apply(double corner1, double corner2, double corner3, double corner4, double corner5);
  213.     }

  214. }