Class CategoryList

All Implemented Interfaces:
Serializable, Iterable<Category>, Collection<Category>, List<Category>, SequencedCollection<Category>, org.opengis.referencing.operation.MathTransform, org.opengis.referencing.operation.MathTransform1D

final class CategoryList extends AbstractList<Category> implements org.opengis.referencing.operation.MathTransform1D, Serializable
An immutable list of categories and a transfer function implementation backed by that list. The category list (exposed by the List interface) has the following properties:
  • Categories are sorted by their sample values.
  • Overlapping ranges of sample values are not allowed.
  • A CategoryList can contain a mix of qualitative and quantitative categories.
The transfer function exposed by the MathTransform1D interface is used only if this list contains at least 2 categories. More specifically:
  • If this list contains 0 category, then the transfer function shall be absent.
  • If this list contains 1 category, then the transfer function should be the function provided by that single category, without the indirection level implemented by CategoryList.
  • If this list contains 2 or more categories, then the transfer function implementation provided by this CategoryList is necessary for searching the category where belong each sample value.
The transfer function allows some extrapolations if a sample values to convert falls in a gap between two categories. The category immediately below will be used (i.e. its domain is expanded up to the next category), except if one category is qualitative while the next category is quantitative. In the latter case, the quantitative category has precedence. The reason for allowing some extrapolations is because the range of values given to Category are often only estimations, and we don't want the transfer function to fail because a value is slightly outside the estimated domain.

Instances of CategoryList are immutable and thread-safe.

Since:
1.0
Version:
1.2
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private final Category[]
    The list of categories to use for decoding samples.
    (package private) final CategoryList
    The CategoryList that describes values after transfer function has been applied, or if this CategoryList is already converted then the original CategoryList.
    private final double[]
    Minimum and maximum values (inclusive) of Category.converse for each category.
    (package private) static final CategoryList
    An empty list of categories.
    private final double
    The action to take in transform(…) methods when converting a NaN value to sample value and no mapping is found for that specific NaN value.
    private int
    Index of the last used category.
    private final double[]
    List of minimum values (inclusive) for each category in categories, in strictly increasing order.
    (package private) final NumberRange<?>
    The union of the ranges of every categories, excluding NaN values.
    private static final long
    Serial number for inter-operability with different versions.

    Fields inherited from class java.util.AbstractList

    modCount
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    private
    The constructor for the EMPTY constant.
    private
    CategoryList(Category[] categories, CategoryList converse, Number background)
    Constructs a category list using the specified array of categories.
  • Method Summary

    Modifier and Type
    Method
    Description
    (package private) final boolean
    Returns true if the category list contains at least one NaN value.
    (package private) static int
    binarySearch(double[] minimums, double sample)
    Performs a bi-linear search of the specified value in the given sorted array.
    (package private) static CategoryList
    create(Category[] categories, Number background)
    Constructs a category list using the specified array of categories.
    final double
    derivative(double value)
    Gets the derivative of this function at a value.
    final org.opengis.referencing.operation.Matrix
    derivative(org.opengis.geometry.DirectPosition point)
    Gets the derivative of this transform at a point.
    private static void
    ensureNonNull(Object srcPts, Object dstPts)
    Ensures that the given arrays are non-null.
    boolean
    equals(Object object)
    Compares the specified object with this category list for equality.
    private static String
    formatNoCategory(double value)
    Formats the "No category for value" message.
    final Category
    get(int i)
    Returns the element at the specified position in this list.
    final int
    Gets the dimension of input points, which is 1.
    final int
    Gets the dimension of output points, which is 1.
    (package private) final org.opengis.referencing.operation.MathTransform1D
    Returns the transfer function from sample values to real values, including conversion of "no data" values to NaNs.
    final org.opengis.referencing.operation.MathTransform1D
    Returns the inverse transform of this object, which may be this if this transform is identity.
    boolean
    Tests whether this transform does not move any points.
    private Object
    Returns a shared instance if applicable.
    (package private) final Category
    search(double sample)
    Returns the category of the specified sample value.
    final int
    Returns the number of categories in this list.
    Returns a Well Known Text (WKT) for this object.
    final double
    transform(double value)
    Transforms the specified value.
    private void
    transform(double[] srcPts, float[] srcFloat, int srcOff, double[] dstPts, float[] dstFloat, int dstOff, int numPts)
    Transforms a list of coordinate values.
    final void
    transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
    Transforms a list of coordinate values.
    final void
    transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)
    Transforms a list of coordinate values.
    final void
    transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts)
    Transforms a list of coordinate values.
    final void
    transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts)
    Transforms a list of coordinate values.
    final org.opengis.geometry.DirectPosition
    transform(org.opengis.geometry.DirectPosition ptSrc, org.opengis.geometry.DirectPosition ptDst)
    Transforms the specified ptSrc and stores the result in ptDst.
    private double
    unmappedValue(double value)
    Invoked when a value cannot be located in the minimums array.

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait

    Methods inherited from interface java.util.Collection

    parallelStream, removeIf, stream, toArray

    Methods inherited from interface java.lang.Iterable

    forEach
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serial number for inter-operability with different versions.
      See Also:
    • EMPTY

      static final CategoryList EMPTY
      An empty list of categories.
    • range

      final NumberRange<?> range
      The union of the ranges of every categories, excluding NaN values. May be null if this list has no non-NaN category.

      A NumberRange object gives more information than a (minimum, maximum) tuple since it also contains the type (integer, float, etc.) and inclusion/exclusion information.

    • minimums

      private final double[] minimums
      List of minimum values (inclusive) for each category in categories, in strictly increasing order. For each category, minimums[i] is often equal to categories[i].range.getMinDouble(true) but may also be lower for filling the gap between a quantitative category and its preceding qualitative category. We do not store maximum values; range of a category is assumed to span up to the start of the next category.

      This array must be in increasing order, with Double.NaN values last. This is the need to sort this array that determines the element order in categories.

    • categories

      private final Category[] categories
      The list of categories to use for decoding samples. This list must be sorted in increasing order of Category.range minimum. Qualitative categories with NaN values are last.
    • converseRanges

      private final double[] converseRanges
      Minimum and maximum values (inclusive) of Category.converse for each category. For each category at index i, the converse minimum is at index i*2 and the converse maximum is at index i*2+1. This information is used for ensuring that extrapolated values (i.e. the result of a conversion when the input value was not in the range of any category) do not accidentally fall in the range of another category. This field may be null if there is no need to perform such verification because there is less than 2 categories bounded by real (non-NaN) values.
    • lastUsed

      private transient int lastUsed
      Index of the last used category. We assume that this category is the most likely to be requested in the next transform(…) method invocation. This field does not need to be volatile because it is not a problem if a thread see an outdated value; this is only a hint, and the arrays used with this index are immutable.
    • converse

      final CategoryList converse
      The CategoryList that describes values after transfer function has been applied, or if this CategoryList is already converted then the original CategoryList. Never null, but may be this if the transfer function is the identity function. May also be EMPTY if this category list has no quantitative category.

      Except for the EMPTY special case, this field establishes a bidirectional navigation between sample values and real values. This is in contrast with methods named converted(), which establish a unidirectional navigation from sample values to real values.

      See Also:
    • fallback

      private final double fallback
      The action to take in transform(…) methods when converting a NaN value to sample value and no mapping is found for that specific NaN value. The action can be one of the following, in preference order:
      • +0 means to leave the NaN value as-is. In such case, casting the NaN value to an integer will produce 0 (so the 0 value is not set explicitly, but obtained as a result of casting to integer). This action can be taken only if no category include the 0 value, or if 0 is for the background.
      • Any non-zero and non-NaN value means to use that value directly. In such case, the value should be SampleDimension.background.
      • Double.NaN means that none of the above can be applied, in which case an exception will be thrown.
      See Also:
  • Constructor Details

    • CategoryList

      private CategoryList()
      The constructor for the EMPTY constant.
    • CategoryList

      private CategoryList(Category[] categories, CategoryList converse, Number background)
      Constructs a category list using the specified array of categories. The categories array should contain at least one element, otherwise the EMPTY constant should be used.
      Parameters:
      categories - the list of categories. This array is not cloned and is modified in-place.
      converse - if we are creating the list of categories after conversion from samples to real values, the original list before conversion. Otherwise null.
      background - the SampleDimension.background sample value as a real number (not NaN), or null. Despite being a sample value, this is used only for constructing the converted category list (converse != null) because this is used as a fallback for inverse transforms.
      Throws:
      IllegalSampleDimensionException - if two or more categories have overlapping sample value range.
  • Method Details

    • readResolve

      private Object readResolve() throws ObjectStreamException
      Returns a shared instance if applicable.
      Returns:
      the object to use after deserialization.
      Throws:
      ObjectStreamException - if the serialized object contains invalid data.
    • create

      static CategoryList create(Category[] categories, Number background)
      Constructs a category list using the specified array of categories. The categories array should contain at least one element, otherwise the EMPTY constant should be used.

      This is defined as a static method for allowing the addition of a caching mechanism in the future if desired.

      Parameters:
      categories - the list of categories. This array is not cloned and is modified in-place.
      background - the SampleDimension.background value (may be null). This is a sample value (not a NaN value from converted categories).
      Throws:
      IllegalSampleDimensionException - if two or more categories have overlapping sample value range.
    • allowsNaN

      final boolean allowsNaN()
      Returns true if the category list contains at least one NaN value.
    • getTransferFunction

      final org.opengis.referencing.operation.MathTransform1D getTransferFunction()
      Returns the transfer function from sample values to real values, including conversion of "no data" values to NaNs. Callers shall ensure that there is at least one quantitative category before to invoke this method.
      See Also:
    • binarySearch

      static int binarySearch(double[] minimums, double sample)
      Performs a bi-linear search of the specified value in the given sorted array. If an exact match is found, its index is returned. If no exact match is found, index of the highest value smaller than sample is returned. If no such index exists, -1 is returned. Said otherwise, if the return value is positive and the given array is minimums, then this method returns the index in the categories array of the Category to use for a given sample value.

      This method differs from Arrays.binarySearch(double[],double) in the following aspects:

      • It differentiates the various NaN values.
      • It does not differentiate exact matches from insertion points.
      Parameters:
      minimums - minimums.
      sample - the sample value to search.
      Returns:
      index of the category to use, or -1 if none.
    • search

      final Category search(double sample)
      Returns the category of the specified sample value. If no category fits, then this method returns null.
      Parameters:
      sample - the value.
      Returns:
      the category of the supplied value, or null.
    • unmappedValue

      private double unmappedValue(double value) throws org.opengis.referencing.operation.TransformException
      Invoked when a value cannot be located in the minimums array. It should happen only for NaN input values, which in turn should happen only in "unit to sample" conversions. In such case we fallback on zero value if non ambiguous, or on the background value if available, or throw an exception otherwise.
      Parameters:
      value - the (usually NaN) value that we cannot map to a category range.
      Returns:
      the value to use as converted value.
      Throws:
      org.opengis.referencing.operation.TransformException - if the value cannot be converted.
    • formatNoCategory

      private static String formatNoCategory(double value)
      Formats the "No category for value" message.
    • transform

      private void transform(double[] srcPts, float[] srcFloat, int srcOff, double[] dstPts, float[] dstFloat, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate values. This implementation accepts float or double arrays, since the quasi-totality of the implementation is the same. Locale variables still of the double type because this is the type used in Category objects.
      Throws:
      org.opengis.referencing.operation.TransformException
    • ensureNonNull

      private static void ensureNonNull(Object srcPts, Object dstPts)
      Ensures that the given arrays are non-null.
    • transform

      public final void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate values. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • transform

      public final void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate values. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • transform

      public final void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate values. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • transform

      public final void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int numPts) throws org.opengis.referencing.operation.TransformException
      Transforms a list of coordinate values. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • transform

      public final double transform(double value) throws org.opengis.referencing.operation.TransformException
      Transforms the specified value. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform1D
      Parameters:
      value - the value to transform.
      Returns:
      the transformed value.
      Throws:
      org.opengis.referencing.operation.TransformException - if the value cannot be transformed.
    • derivative

      public final double derivative(double value) throws org.opengis.referencing.operation.TransformException
      Gets the derivative of this function at a value. This method can be invoked only if categories contains at least two elements, otherwise a MathTransform implementation from another package is used.
      Specified by:
      derivative in interface org.opengis.referencing.operation.MathTransform1D
      Parameters:
      value - the value where to evaluate the derivative.
      Returns:
      the derivative at the specified point.
      Throws:
      org.opengis.referencing.operation.TransformException - if the derivative cannot be evaluated at the specified point.
    • transform

      public final org.opengis.geometry.DirectPosition transform(org.opengis.geometry.DirectPosition ptSrc, org.opengis.geometry.DirectPosition ptDst) throws org.opengis.referencing.operation.TransformException
      Transforms the specified ptSrc and stores the result in ptDst.
      Specified by:
      transform in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • derivative

      public final org.opengis.referencing.operation.Matrix derivative(org.opengis.geometry.DirectPosition point) throws org.opengis.referencing.operation.TransformException
      Gets the derivative of this transform at a point.
      Specified by:
      derivative in interface org.opengis.referencing.operation.MathTransform
      Throws:
      org.opengis.referencing.operation.TransformException
    • isIdentity

      public boolean isIdentity()
      Tests whether this transform does not move any points.
      Specified by:
      isIdentity in interface org.opengis.referencing.operation.MathTransform
    • inverse

      public final org.opengis.referencing.operation.MathTransform1D inverse()
      Returns the inverse transform of this object, which may be this if this transform is identity.
      Specified by:
      inverse in interface org.opengis.referencing.operation.MathTransform
      Specified by:
      inverse in interface org.opengis.referencing.operation.MathTransform1D
    • getSourceDimensions

      public final int getSourceDimensions()
      Gets the dimension of input points, which is 1.
      Specified by:
      getSourceDimensions in interface org.opengis.referencing.operation.MathTransform
    • getTargetDimensions

      public final int getTargetDimensions()
      Gets the dimension of output points, which is 1.
      Specified by:
      getTargetDimensions in interface org.opengis.referencing.operation.MathTransform
    • size

      public final int size()
      Returns the number of categories in this list.
      Specified by:
      size in interface Collection<Category>
      Specified by:
      size in interface List<Category>
      Specified by:
      size in class AbstractCollection<Category>
    • get

      public final Category get(int i)
      Returns the element at the specified position in this list.
      Specified by:
      get in interface List<Category>
      Specified by:
      get in class AbstractList<Category>
    • equals

      public boolean equals(Object object)
      Compares the specified object with this category list for equality.
      Specified by:
      equals in interface Collection<Category>
      Specified by:
      equals in interface List<Category>
      Overrides:
      equals in class AbstractList<Category>
    • toWKT

      public String toWKT() throws UnsupportedOperationException
      Returns a Well Known Text (WKT) for this object. This operation may fail if an object is too complex for the WKT format capability.
      Specified by:
      toWKT in interface org.opengis.referencing.operation.MathTransform
      Returns:
      the Well Know Text for this object.
      Throws:
      UnsupportedOperationException - if this object cannot be formatted as WKT.