LCOV - code coverage report
Current view: top level - frmts/vrt - vrtreclassifier.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 11 11 100.0 %
Date: 2025-05-31 00:00:17 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             : *
       3             :  * Project:  Virtual GDAL Datasets
       4             :  * Purpose:  Implementation of Reclassifier
       5             :  * Author:   Daniel Baston
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, ISciences LLC
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #pragma once
      14             : 
      15             : #include "gdal.h"
      16             : #include "cpl_error.h"
      17             : 
      18             : #include <map>
      19             : #include <optional>
      20             : #include <utility>
      21             : #include <vector>
      22             : 
      23             : namespace gdal
      24             : {
      25             : 
      26             : /**
      27             :  * Class to manage reclassification of pixel values
      28             :  */
      29             : class Reclassifier
      30             : {
      31             :   public:
      32             :     /// Character separating elements in a list of mapping
      33             :     static constexpr char MAPPING_INTERVAL_SEP_CHAR = ';';
      34             : 
      35             :     /// Character separating source interval from target value
      36             :     static constexpr char MAPPING_FROMTO_SEP_CHAR = '=';
      37             : 
      38             :     /**
      39             :      * Internal struct to hold an interval of values to be reclassified
      40             :      */
      41             :     struct Interval
      42             :     {
      43             :         /// minimum value of range
      44             :         double dfMin;
      45             : 
      46             :         /// maximum value of range
      47             :         double dfMax;
      48             : 
      49             :         /// Set the interval to represent a single value [x,x]
      50             :         void SetToConstant(double dfVal);
      51             : 
      52             :         /** Parse an interval. The interval may be either a single constant value,
      53             :          *  or two comma-separated values enclosed by parentheses/brackets to
      54             :          *  represent open/closed intervals.
      55             :          *
      56             :          * @param pszText string from which to parse an interval
      57             :          * @param end pointer to first non-consumed character
      58             :          * @return CE_None on success, CE_Failure otherwise
      59             :          */
      60             :         CPLErr Parse(const char *pszText, char **end);
      61             : 
      62             :         /// Returns true of the interval represents a single value [x,x]
      63             :         bool IsConstant() const
      64             :         {
      65             :             return dfMin == dfMax;
      66             :         }
      67             : 
      68             :         /// Returns true if the interval contains a value
      69      104705 :         bool Contains(double x) const
      70             :         {
      71      104705 :             return x >= dfMin && x <= dfMax;
      72             :         }
      73             : 
      74             :         /// Returns true if the intervals overlap
      75             :         bool Overlaps(const Interval &other) const;
      76             :     };
      77             : 
      78             :     /** Initialize a Reclassifier from text. The text consists of a series of
      79             :      *  SOURCE=DEST mappings, separated by a semicolon.
      80             :      *
      81             :      *  Each SOURCE element much be one of:
      82             :      *  - a constant value
      83             :      *  - a range of values, such as (3, 4] or [7, inf]
      84             :      *  - the value NO_DATA, for which the provided NoData value will be
      85             :      *    substituted
      86             :      *  - the value DEFAULT, to define a DEST for any value that does not
      87             :      *    match another SOURCE mapping
      88             :      *
      89             :      *  Each DEST element must be one of:
      90             :      *  - a constant value
      91             :      *  - the value NO_DATA, for which the provided NoData value will be
      92             :      *    substituted
      93             :      *
      94             :      *  An error will be returned if:
      95             :      *  - NO_DATA is used by a NoData value is not defined.
      96             :      *  - a DEST value does not fit into the destination data type
      97             :      *
      98             :      * @param pszText text to parse
      99             :      * @param noDataValue NoData value
     100             :      * @param eBufType Destination data type
     101             :      * @return CE_None if no errors occurred, CE_Failure otherwise
     102             :      */
     103             :     CPLErr Init(const char *pszText, std::optional<double> noDataValue,
     104             :                 GDALDataType eBufType);
     105             : 
     106             :     /** Set a mapping between an interval and (optionally) a destination value.
     107             :      *  If no destination value is provided, values matching the interval
     108             :      *  will be passed through unmodified. It will not be verified that these values
     109             :      *  fit within the destination data type.
     110             :      */
     111             :     void AddMapping(const Interval &interval, std::optional<double> dfDstVal);
     112             : 
     113             :     /** Reclassify a value
     114             :      *
     115             :      * @param srcVal the value to reclassify
     116             :      * @param bFoundInterval set to True if the value could be reclassified
     117             :      * @return the reclassified value
     118             :      */
     119             :     double Reclassify(double srcVal, bool &bFoundInterval) const;
     120             : 
     121             :     /** If true, values not matched by any interval will be
     122             :      *  returned unmodified. It will not be verified that these values
     123             :      *  fit within the destination data type.
     124             :      */
     125           1 :     void SetDefaultPassThrough(bool value)
     126             :     {
     127           1 :         m_defaultPassThrough = value;
     128           1 :     }
     129             : 
     130             :     /** Sets a default value for any value not matched by any interval.
     131             :      */
     132           9 :     void SetDefaultValue(double value)
     133             :     {
     134           9 :         m_defaultValue = value;
     135           9 :     }
     136             : 
     137             :     /** Sets a value for an input NaN value
     138             :      */
     139           1 :     void SetNaNValue(double value)
     140             :     {
     141           1 :         m_NaNValue = value;
     142           1 :     }
     143             : 
     144             :     /** Prepare reclassifier for use. No more mappings may be added.
     145             :      */
     146             :     CPLErr Finalize();
     147             : 
     148             :   private:
     149             :     /// mapping of ranges to outputs
     150             :     std::vector<std::pair<Interval, std::optional<double>>>
     151             :         m_aoIntervalMappings{};
     152             : 
     153             :     /// output value for NaN inputs
     154             :     std::optional<double> m_NaNValue{};
     155             : 
     156             :     /// output value for inputs not matching any Interval
     157             :     std::optional<double> m_defaultValue{};
     158             : 
     159             :     /// whether to pass unmatched inputs through unmodified
     160             :     bool m_defaultPassThrough{false};
     161             : };
     162             : 
     163             : }  // namespace gdal

Generated by: LCOV version 1.14