Patera2005.java

  1. /* Copyright 2002-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.ssa.collision.shorttermencounter.probability.twod;

  18. import org.hipparchus.CalculusFieldElement;
  19. import org.hipparchus.Field;
  20. import org.hipparchus.analysis.CalculusFieldUnivariateFunction;
  21. import org.hipparchus.analysis.UnivariateFunction;
  22. import org.hipparchus.analysis.integration.FieldUnivariateIntegrator;
  23. import org.hipparchus.analysis.integration.TrapezoidIntegrator;
  24. import org.hipparchus.analysis.integration.UnivariateIntegrator;
  25. import org.hipparchus.util.FastMath;
  26. import org.hipparchus.util.FieldSinCos;
  27. import org.hipparchus.util.MathArrays;
  28. import org.hipparchus.util.MathUtils;
  29. import org.hipparchus.util.SinCos;
  30. import org.orekit.ssa.metrics.FieldProbabilityOfCollision;
  31. import org.orekit.ssa.metrics.ProbabilityOfCollision;

  32. /**
  33.  * Compute the probability of collision using the method described in :"PATERA, Russell P. Calculating collision probability
  34.  * for arbitrary space vehicle shapes via numerical quadrature. Journal of guidance, control, and dynamics, 2005, vol. 28, no
  35.  * 6, p. 1326-1328.".
  36.  * <p>
  37.  * It is one of the recommended methods to use.
  38.  * <p>
  39.  * It assumes :
  40.  * <ul>
  41.  *     <li>Short encounter leading to a linear relative motion.</li>
  42.  *     <li>Spherical collision object (in this implementation only. The method could be used on non spherical object).</li>
  43.  *     <li>Uncorrelated positional covariance.</li>
  44.  *     <li>Gaussian distribution of the position uncertainties.</li>
  45.  *     <li>Deterministic velocity i.e. no velocity uncertainties.</li>
  46.  * </ul>
  47.  * It has been rewritten to use Orekit specific inputs.
  48.  *
  49.  * @author Vincent Cucchietti
  50.  * @since 12.0
  51.  */
  52. public class Patera2005 extends AbstractShortTermEncounter1DNumerical2DPOCMethod {

  53.     /** Default threshold defining if miss-distance and combined radius are considered equal (+- 10 cm). */
  54.     private static final double DEFAULT_EQUALITY_THRESHOLD = 1e-1;

  55.     /**
  56.      * Default constructor built with the following trapezoid integrator:
  57.      * <ul>
  58.      *     <li>Minimal iteration count of 5</li>
  59.      *     <li>Maximum iteration count of 50000</li>
  60.      * </ul>.
  61.      */
  62.     public Patera2005() {
  63.         this(new TrapezoidIntegrator(5, TrapezoidIntegrator.TRAPEZOID_MAX_ITERATIONS_COUNT), 50000);
  64.     }

  65.     /**
  66.      * Customizable constructor.
  67.      *
  68.      * @param integrator integrator
  69.      * @param maxNbOfEval max number of evaluation
  70.      */
  71.     public Patera2005(final UnivariateIntegrator integrator, final int maxNbOfEval) {
  72.         super("PATERA_2005", integrator, maxNbOfEval);
  73.     }

  74.     /** {@inheritDoc} */
  75.     @Override
  76.     public ProbabilityOfCollision compute(final double xm, final double ym,
  77.                                           final double sigmaX, final double sigmaY,
  78.                                           final double radius,
  79.                                           final UnivariateIntegrator integrator,
  80.                                           final int customMaxNbOfEval) {

  81.         // Depending on miss distance and the combined radius, three distinct cases exist
  82.         final double value;
  83.         final double missDistance = FastMath.sqrt(xm * xm + ym * ym);

  84.         // reference outside the hardbody area, first part of eq(11) is equal to 0
  85.         if (missDistance > radius + DEFAULT_EQUALITY_THRESHOLD) {
  86.             final CommonPateraFunction function = new CommonPateraFunction(xm, ym, sigmaX, sigmaY, radius);
  87.             value = -integrator.integrate(customMaxNbOfEval, function, 0, MathUtils.TWO_PI) / MathUtils.TWO_PI;

  88.         }

  89.         // reference within the hardbody area, first part of eq(11) is equal to 1
  90.         else if (missDistance < radius - DEFAULT_EQUALITY_THRESHOLD) {
  91.             final CommonPateraFunction function = new CommonPateraFunction(xm, ym, sigmaX, sigmaY, radius);
  92.             value = 1 - integrator.integrate(customMaxNbOfEval, function, 0, MathUtils.TWO_PI) / MathUtils.TWO_PI;
  93.         }

  94.         // Peculiar case where miss distance = combined radius, r may be equal to zero so eq(9) must be used
  95.         else {
  96.             final PateraFunctionSpecialCase function = new PateraFunctionSpecialCase(xm, ym, sigmaX, sigmaY, radius);
  97.             value = integrator.integrate(customMaxNbOfEval, function, 0, MathUtils.TWO_PI) / MathUtils.TWO_PI;
  98.         }

  99.         return new ProbabilityOfCollision(value, 0, 0, getName(), isAMaximumProbabilityOfCollisionMethod());
  100.     }

  101.     /** {@inheritDoc} */
  102.     @Override
  103.     public <T extends CalculusFieldElement<T>> FieldProbabilityOfCollision<T> compute(final T xm, final T ym,
  104.                                                                                       final T sigmaX, final T sigmaY,
  105.                                                                                       final T radius,
  106.                                                                                       final FieldUnivariateIntegrator<T> customIntegrator,
  107.                                                                                       final int customMaxNbOfEval) {
  108.         // Depending on miss distance and the combined radius, three distinct cases exist
  109.         final Field<T> field      = xm.getField();
  110.         final T        zero       = field.getZero();
  111.         final T        one        = field.getOne();
  112.         final T        twoPiField = one.newInstance(MathUtils.TWO_PI);

  113.         final T      value;
  114.         final double missDistance = xm.square().add(ym.square()).sqrt().getReal();
  115.         final double radiusReal   = radius.getReal();

  116.         // Reference outside the hardbody area, first part of eq(11) is equal to 0
  117.         if (missDistance > radiusReal + DEFAULT_EQUALITY_THRESHOLD) {
  118.             final CommonFieldPateraFunction<T> function =
  119.                     new CommonFieldPateraFunction<>(xm, ym, sigmaX, sigmaY, radius);
  120.             value = customIntegrator.integrate(customMaxNbOfEval, function, zero, twoPiField).divide(twoPiField).negate();
  121.         }

  122.         // Reference within the hardbody area, first part of eq(11) is equal to 1
  123.         else if (missDistance < radiusReal - DEFAULT_EQUALITY_THRESHOLD) {
  124.             final CommonFieldPateraFunction<T> function =
  125.                     new CommonFieldPateraFunction<>(xm, ym, sigmaX, sigmaY, radius);
  126.             value = one.subtract(
  127.                     customIntegrator.integrate(customMaxNbOfEval, function, zero, twoPiField).divide(twoPiField));
  128.         }

  129.         // Peculiar case where miss distance = combined radius, r may be equal to zero so eq(9) must be used
  130.         else {
  131.             final FieldPateraFunctionSpecialCase<T> function =
  132.                     new FieldPateraFunctionSpecialCase<>(xm, ym, sigmaX, sigmaY, radius);
  133.             value = customIntegrator.integrate(customMaxNbOfEval, function, zero, twoPiField).divide(twoPiField);
  134.         }

  135.         return new FieldProbabilityOfCollision<>(value, zero, zero, getName(), isAMaximumProbabilityOfCollisionMethod());
  136.     }

  137.     /** {@inheritDoc} */
  138.     @Override
  139.     public ShortTermEncounter2DPOCMethodType getType() {
  140.         return ShortTermEncounter2DPOCMethodType.PATERA_2005;
  141.     }

  142.     /** Commonly used function used in equation (11) in Patera's paper. */
  143.     private static class CommonPateraFunction extends AbstractPateraFunction {

  144.         /**
  145.          * Constructor.
  146.          *
  147.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  148.          * (m)
  149.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  150.          * (m)
  151.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  152.          * onto the collision plane (m)
  153.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  154.          * the collision plane (m)
  155.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  156.          */
  157.         private CommonPateraFunction(final double xm, final double ym, final double sigmaX, final double sigmaY,
  158.                                      final double radius) {
  159.             super(xm, ym, sigmaX, sigmaY, radius);
  160.         }

  161.         /** {@inheritDoc} */
  162.         @Override
  163.         public double value(final double xm, final double ym, final double scaleFactor, final double sigma,
  164.                             final double radius, final double theta) {

  165.             final SinCos sinCosTheta = FastMath.sinCos(theta);
  166.             final double sinTheta    = sinCosTheta.sin();
  167.             final double cosTheta    = sinCosTheta.cos();

  168.             final double xPrime   = getXPrime(cosTheta);
  169.             final double yPrime   = getYPrime(sinTheta);
  170.             final double rSquared = getRSquared(xPrime, yPrime);

  171.             return FastMath.exp(-0.5 * rSquared / sigma / sigma) *
  172.                     (radius * scaleFactor * MathArrays.linearCombination(xm, cosTheta, ym, sinTheta) +
  173.                             scaleFactor * radius * radius) / rSquared;
  174.         }
  175.     }

  176.     /**
  177.      * Function used in the rare case where miss distance = combined radius. It represents equation (9) in Patera's paper but
  178.      * has been modified to be used with Orekit specific inputs.
  179.      */
  180.     private static class PateraFunctionSpecialCase extends AbstractPateraFunction {

  181.         /**
  182.          * Constructor.
  183.          *
  184.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  185.          * (m)
  186.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  187.          * (m)
  188.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  189.          * onto the collision plane (m)
  190.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  191.          * the collision plane (m)
  192.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  193.          */
  194.         private PateraFunctionSpecialCase(final double xm, final double ym, final double sigmaX,
  195.                                           final double sigmaY, final double radius) {
  196.             super(xm, ym, sigmaX, sigmaY, radius);
  197.         }

  198.         /** {@inheritDoc} */
  199.         @Override
  200.         public double value(final double xm, final double ym, final double scaleFactor, final double sigma,
  201.                             final double radius, final double theta) {

  202.             final SinCos sinCosTheta = FastMath.sinCos(theta);
  203.             final double sinTheta    = sinCosTheta.sin();
  204.             final double cosTheta    = sinCosTheta.cos();

  205.             final double xPrime = getXPrime(cosTheta);
  206.             final double yPrime = getYPrime(sinTheta);

  207.             final double rSquared          = getRSquared(xPrime, yPrime);
  208.             final double sigmaSquared      = sigma * sigma;
  209.             final double oneOverTwoSigmaSq = 1. / (2 * sigmaSquared);
  210.             final double rSqOverTwoSigmaSq = oneOverTwoSigmaSq * rSquared;

  211.             return radius * scaleFactor * (MathArrays.linearCombination(xm, cosTheta, ym, sinTheta) + radius) *
  212.                     oneOverTwoSigmaSq * (1 - rSqOverTwoSigmaSq * (0.5 - rSqOverTwoSigmaSq * (1. / 6 - rSqOverTwoSigmaSq * (
  213.                     1. / 24 - rSqOverTwoSigmaSq / 720))));

  214.         }
  215.     }

  216.     /** Abstract class for different functions used in Patera's paper. */
  217.     private abstract static class AbstractPateraFunction implements UnivariateFunction {
  218.         /**
  219.          * Position on the x-axis of the rotated encounter frame.
  220.          */
  221.         private final double xm;

  222.         /**
  223.          * Position on the y-axis of the rotated encounter frame.
  224.          */
  225.         private final double ym;

  226.         /**
  227.          * Recurrent term used in Patera 2005 formula.
  228.          */
  229.         private final double scaleFactor;

  230.         /**
  231.          * General sigma after symmetrization.
  232.          */
  233.         private final double sigma;

  234.         /**
  235.          * Hardbody radius (m).
  236.          */
  237.         private final double radius;

  238.         /**
  239.          * Constructor.
  240.          *
  241.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  242.          * (m)
  243.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  244.          * (m)
  245.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  246.          * onto the collision plane (m)
  247.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  248.          * the collision plane (m)
  249.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  250.          */
  251.         AbstractPateraFunction(final double xm, final double ym, final double sigmaX, final double sigmaY,
  252.                                final double radius) {
  253.             this.xm          = xm;
  254.             this.ym          = ym;
  255.             this.scaleFactor = sigmaY / sigmaX;
  256.             this.sigma       = sigmaY;
  257.             this.radius      = radius;
  258.         }

  259.         /**
  260.          * Compute the value of the function.
  261.          *
  262.          * @param theta angle at which the function value should be evaluated
  263.          *
  264.          * @return the value of the function
  265.          *
  266.          * @throws IllegalArgumentException when the activated method itself can ascertain that a precondition, specified in
  267.          * the API expressed at the level of the activated method, has been violated. When Hipparchus throws an
  268.          * {@code IllegalArgumentException}, it is usually the consequence of checking the actual parameters passed to the
  269.          * method.
  270.          */
  271.         public double value(final double theta) {
  272.             return value(xm, ym, scaleFactor, sigma, radius, theta);
  273.         }

  274.         /**
  275.          * Compute the value of the defined Patera function for input theta.
  276.          *
  277.          * @param x secondary collision object projected position onto the collision plane in the rotated encounter frame
  278.          * x-axis (m)
  279.          * @param y secondary collision object projected position onto the collision plane in the rotated encounter frame
  280.          * y-axis (m)
  281.          * @param scale scale factor used to symmetrize the probability density of collision, equal to sigmaY / sigmaX
  282.          * @param symmetrizedSigma symmetrized position sigma equal to sigmaY
  283.          * @param combinedRadius sum of primary and secondary collision object equivalent sphere radii (m)
  284.          * @param theta current angle of evaluation of the deformed hardbody radius (rad)
  285.          *
  286.          * @return value of the defined Patera function for input conjunction and theta
  287.          */
  288.         public abstract double value(double x, double y, double scale, double symmetrizedSigma, double combinedRadius,
  289.                                      double theta);

  290.         /**
  291.          * Get current x-axis component to the deformed hardbody perimeter.
  292.          *
  293.          * @param cosTheta cos of the angle determining deformed hardbody radius x-axis component to compute
  294.          *
  295.          * @return current x-axis component to the deformed hardbody perimeter
  296.          */
  297.         public double getXPrime(final double cosTheta) {
  298.             return scaleFactor * (xm + radius * cosTheta);
  299.         }

  300.         /**
  301.          * Get current y-axis component to the deformed hardbody perimeter.
  302.          *
  303.          * @param sinTheta sin of the angle determining deformed hardbody radius y-axis component to compute
  304.          *
  305.          * @return current y-axis component to the deformed hardbody perimeter
  306.          */
  307.         public double getYPrime(final double sinTheta) {
  308.             return ym + radius * sinTheta;
  309.         }

  310.         /**
  311.          * Get current distance from the reference to the determined hardbody perimeter.
  312.          *
  313.          * @param xPrime current x-axis component to the deformed hardbody perimeter
  314.          * @param yPrime current y-axis component to the deformed hardbody perimeter
  315.          *
  316.          * @return current distance from the reference to the determined hardbody perimeter
  317.          */
  318.         public double getRSquared(final double xPrime, final double yPrime) {
  319.             return xPrime * xPrime + yPrime * yPrime;
  320.         }
  321.     }

  322.     /** Commonly used function used in equation (11) in Patera's paper. */
  323.     private static class CommonFieldPateraFunction<T extends CalculusFieldElement<T>>
  324.             extends AbstractFieldPateraFunction<T> {

  325.         /**
  326.          * Constructor.
  327.          *
  328.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  329.          * (m)
  330.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  331.          * (m)
  332.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  333.          * onto the collision plane (m)
  334.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  335.          * the collision plane (m)
  336.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  337.          */
  338.         private CommonFieldPateraFunction(final T xm, final T ym, final T sigmaX, final T sigmaY,
  339.                                           final T radius) {
  340.             super(xm, ym, sigmaX, sigmaY, radius);
  341.         }

  342.         /** {@inheritDoc} */
  343.         @Override
  344.         public T value(final T xm, final T ym, final T scaleFactor, final T sigma,
  345.                        final T radius, final T theta) {

  346.             final FieldSinCos<T> sinCosTheta = theta.sinCos();
  347.             final T              sinTheta    = sinCosTheta.sin();
  348.             final T              cosTheta    = sinCosTheta.cos();

  349.             final T xPrime   = getXPrime(cosTheta);
  350.             final T yPrime   = getYPrime(sinTheta);
  351.             final T rSquared = getRSquared(xPrime, yPrime);

  352.             return rSquared.divide(sigma.square()).multiply(-0.5).exp()
  353.                            .multiply(radius.multiply(scaleFactor).multiply(xm.multiply(cosTheta)
  354.                                                                              .add(ym.multiply(sinTheta)))
  355.                                            .add(scaleFactor.multiply(radius.square()))).divide(rSquared);
  356.         }

  357.     }

  358.     /**
  359.      * Function used in the rare case where miss distance = combined radius. It represents equation (9) in Patera's paper but
  360.      * has been modified to be used with Orekit specific inputs.
  361.      */
  362.     private static class FieldPateraFunctionSpecialCase<T extends CalculusFieldElement<T>>
  363.             extends AbstractFieldPateraFunction<T> {

  364.         /**
  365.          * Constructor.
  366.          *
  367.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  368.          * (m)
  369.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  370.          * (m)
  371.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  372.          * onto the collision plane (m)
  373.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  374.          * the collision plane (m)
  375.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  376.          */
  377.         private FieldPateraFunctionSpecialCase(final T xm, final T ym, final T sigmaX,
  378.                                                final T sigmaY, final T radius) {
  379.             super(xm, ym, sigmaX, sigmaY, radius);
  380.         }

  381.         /** {@inheritDoc} */
  382.         @Override
  383.         public T value(final T xm, final T ym, final T scaleFactor, final T sigma,
  384.                        final T radius, final T theta) {

  385.             final FieldSinCos<T> sinCosTheta = theta.sinCos();
  386.             final T              sinTheta    = sinCosTheta.sin();
  387.             final T              cosTheta    = sinCosTheta.cos();

  388.             final T xPrime            = scaleFactor.multiply(xm).add(scaleFactor.multiply(radius).multiply(cosTheta));
  389.             final T yPrime            = ym.add(radius.multiply(sinTheta));
  390.             final T rSquared          = xPrime.square().add(yPrime.square());
  391.             final T sigmaSquared      = sigma.multiply(sigma);
  392.             final T oneOverTwoSigmaSq = sigmaSquared.multiply(2.).reciprocal();
  393.             final T rSqOverTwoSigmaSq = rSquared.multiply(oneOverTwoSigmaSq);

  394.             // Recursive approach to maximize usage of the same fielded variables
  395.             return radius.multiply(scaleFactor).multiply(xm.multiply(cosTheta).add(ym.multiply(sinTheta)).add(radius))
  396.                          .multiply(oneOverTwoSigmaSq.negate()
  397.                                                     .multiply(rSqOverTwoSigmaSq
  398.                                                                       .multiply(rSqOverTwoSigmaSq
  399.                                                                                         .multiply(rSqOverTwoSigmaSq
  400.                                                                                                           .multiply(
  401.                                                                                                                   rSqOverTwoSigmaSq.multiply(
  402.                                                                                                                                            -1. / 720)
  403.                                                                                                                                    .add(1. / 24))
  404.                                                                                                           .subtract(1. / 6))
  405.                                                                                         .add(0.5))
  406.                                                                       .subtract(1.)));
  407.         }
  408.     }

  409.     /** Abstract class for different functions used in Patera's paper. */
  410.     private abstract static class AbstractFieldPateraFunction<T extends CalculusFieldElement<T>> implements
  411.             CalculusFieldUnivariateFunction<T> {
  412.         /**
  413.          * Position on the x-axis of the rotated encounter frame.
  414.          */
  415.         private final T xm;

  416.         /**
  417.          * Position on the y-axis of the rotated encounter frame.
  418.          */
  419.         private final T ym;

  420.         /**
  421.          * Recurrent term used in Patera 2005 formula.
  422.          */
  423.         private final T scaleFactor;

  424.         /**
  425.          * General sigma after symmetrization.
  426.          */
  427.         private final T sigma;

  428.         /**
  429.          * Hardbody radius (m).
  430.          */
  431.         private final T radius;

  432.         /**
  433.          * Constructor.
  434.          *
  435.          * @param xm other collision object projected position onto the collision plane in the rotated encounter frame x-axis
  436.          * (m)
  437.          * @param ym other collision object projected position onto the collision plane in the rotated encounter frame y-axis
  438.          * (m)
  439.          * @param sigmaX square root of the smallest eigen value of the diagonalized combined covariance matrix projected
  440.          * onto the collision plane (m)
  441.          * @param sigmaY square root of the biggest eigen value of the diagonalized combined covariance matrix projected onto
  442.          * the collision plane (m)
  443.          * @param radius sum of primary and secondary collision object equivalent sphere radii (m)
  444.          */
  445.         AbstractFieldPateraFunction(final T xm, final T ym, final T sigmaX, final T sigmaY,
  446.                                     final T radius) {
  447.             this.xm          = xm;
  448.             this.ym          = ym;
  449.             this.scaleFactor = sigmaY.divide(sigmaX);
  450.             this.sigma       = sigmaY;
  451.             this.radius      = radius;
  452.         }

  453.         /**
  454.          * Compute the value of the function.
  455.          *
  456.          * @param theta angle at which the function value should be evaluated
  457.          *
  458.          * @return the value of the function
  459.          *
  460.          * @throws IllegalArgumentException when the activated method itself can ascertain that a precondition, specified in
  461.          * the API expressed at the level of the activated method, has been violated. When Hipparchus throws an
  462.          * {@code IllegalArgumentException}, it is usually the consequence of checking the actual parameters passed to the
  463.          * method.
  464.          */
  465.         @Override
  466.         public T value(final T theta) {
  467.             return value(xm, ym, scaleFactor, sigma, radius, theta);
  468.         }

  469.         /**
  470.          * Compute the value of the defined Patera function for input theta.
  471.          *
  472.          * @param x secondary collision object projected position onto the collision plane in the rotated encounter frame
  473.          * x-axis (m)
  474.          * @param y secondary collision object projected position onto the collision plane in the rotated encounter frame
  475.          * y-axis (m)
  476.          * @param scale scale factor used to symmetrize the probability density of collision, equal to sigmaY / sigmaX
  477.          * @param symmetrizedSigma symmetrized position sigma equal to sigmaY
  478.          * @param combinedRadius sum of primary and secondary collision object equivalent sphere radii (m)
  479.          * @param theta current angle of evaluation of the deformed hardbody radius (rad)
  480.          *
  481.          * @return value of the defined Patera function for input conjunction and theta
  482.          */
  483.         public abstract T value(T x, T y, T scale, T symmetrizedSigma, T combinedRadius,
  484.                                 T theta);

  485.         /**
  486.          * Get current x-axis component to the deformed hardbody perimeter.
  487.          *
  488.          * @param cosTheta cos of the angle determining deformed hardbody radius x-axis component to compute
  489.          *
  490.          * @return current x-axis component to the deformed hardbody perimeter
  491.          */
  492.         public T getXPrime(final T cosTheta) {
  493.             return scaleFactor.multiply(xm).add(scaleFactor.multiply(radius).multiply(cosTheta));
  494.         }

  495.         /**
  496.          * Get current y-axis component to the deformed hardbody perimeter.
  497.          *
  498.          * @param sinTheta sin of the angle determining deformed hardbody radius y-axis component to compute
  499.          *
  500.          * @return current y-axis component to the deformed hardbody perimeter
  501.          */
  502.         public T getYPrime(final T sinTheta) {
  503.             return ym.add(radius.multiply(sinTheta));
  504.         }

  505.         /**
  506.          * Get current distance from the reference to the determined hardbody perimeter.
  507.          *
  508.          * @param xPrime current x-axis component to the deformed hardbody perimeter
  509.          * @param yPrime current y-axis component to the deformed hardbody perimeter
  510.          *
  511.          * @return current distance from the reference to the determined hardbody perimeter
  512.          */
  513.         public T getRSquared(final T xPrime, final T yPrime) {
  514.             return xPrime.multiply(xPrime).add(yPrime.multiply(yPrime));
  515.         }
  516.     }

  517. }