Changes between Version 4 and Version 5 of rfc62_raster_algebra


Ignore:
Timestamp:
Apr 18, 2016, 7:56:30 AM (8 years ago)
Author:
Ari Jolma
Comment:

The new OO C++ API

Legend:

Unmodified
Added
Removed
Modified
  • rfc62_raster_algebra

    v4 v5  
    2121GDAL presents a few problems to raster algebra implementation: 1) the access to data is based on blocks, 2) GDAL supports several datatypes, even complex values, and 3) there is no immediate support for the not-simple data structures needed by some methods (by "method" I refer to functions of raster algebra in this text). In the development version of raster algebra for GDAL (see below the github link) these problems are solved as follows.
    2222
    23 1) The code is organized into two levels: the first one, which loops through all blocks in band(s) and maintains a cache of needed blocks, and the second one, which loops through all cells in a block. The first level is generic one and the method and its arguments just pass through it. The method is passed as a callback and arguments as a void pointer. The second one is method specific, it is where the method is really implemented. The method callbacks must have similar prototype and their return value is used to, e.g., determine whether the block needs to be written to disk etc.
    24 
    25 2) C++ templates are used to convey to the method functions the cell datatype. There is a problem of deducing the datatype (as type) from !RasterBand objects. This is solved currently with switches. The switches become rather large in case of two bands and even more so since some methods can only be fed integer bands. Type traits can be used to test against templated types.
     231) The code is organized into two levels: the first one, which loops through all blocks in band(s) and maintains a cache of needed blocks, and the second one, which loops through all cells in a block. The first level is generic one and the method and its arguments just pass through it. The method is passed as a callback and arguments as pointers to objects of base class. The second one is method specific, it is where the method is really implemented. The method callbacks must have similar prototype and their return value is used to, e.g., determine whether the block needs to be written to disk etc.
     24
     252) C++ templates are used to convey to the method functions the cell datatype.
    2626
    27273) An interface class structure is used for arguments and return values (non-band). The interface classes are not templated, they shadow actual classes, which are templated and use STL as much as possible.
     
    3030// the API:
    3131
    32 // a function to create an argument
    33 gma_object_t *gma_new_object(GDALRasterBand *b, gma_class_t klass);
    34 
    35 // the next two could also be one if arg is null by default
    36 void gma_simple(GDALRasterBand *b, gma_method_t method);
    37 void gma_with_arg(GDALRasterBand *b, gma_method_with_arg_t method, gma_object_t *arg);
    38 
    39 gma_object_t *gma_compute_value(GDALRasterBand *b, gma_method_compute_value_t method, gma_object_t *arg = NULL);
    40 gma_object_t *gma_two_bands(GDALRasterBand *b1, gma_two_bands_method_t method, GDALRasterBand *b2, gma_object_t *arg = NULL);
    41 
    42 // errors are logged with CPLError, so the error status should be checked after every call to these functions
    43 
    44 // arguments can be created into these classes (the list is tentative)
    45 
    46 typedef enum {
    47     gma_number,
    48     gma_integer, // not a real class, used to create a number, which is integer
    49     gma_pair,
    50     gma_range,  // not a real class, used to create a pair of two numbers of band datatype
    51     gma_bins,
    52     gma_histogram,
    53     gma_reclassifier,
    54     gma_cell,
    55     gma_logical_operation
    56 } gma_class_t;
    57 
    58 // the public classes contain only virtual methods
    59 // and they shadow the real classes which are template classes
    60 
    61 // class introspection
    62 // after the class is known, it is legal to cast gma_object_t* to the returned class
    63 virtual gma_class_t get_class() {return gma_XXX;};
    64 
    65 // each class will have methods to build it / retrieve data from it
    66 
    67 // methods are organized into groups according to the API
    68 
    69 // these do not take any arguments and operate on the band in-place
    70 typedef enum {
    71     gma_method_print,
    72     gma_method_rand,
    73     gma_method_abs,
    74     gma_method_exp,
    75     gma_method_exp2,
    76     gma_method_log,
    77     gma_method_log2,
    78     gma_method_log10,
    79     gma_method_sqrt,
    80     gma_method_sin,
    81     gma_method_cos,
    82     gma_method_tan,
    83     gma_method_ceil,
    84     gma_method_floor,
    85     gma_method_set_border_cells
    86 } gma_method_t;
    87 
    88 // these take optionally an argument and compute a value from the band
    89 typedef enum {
    90     gma_method_histogram,
    91     gma_method_zonal_neighbors,
    92     gma_method_get_min,
    93     gma_method_get_max,
    94     gma_method_get_range,
    95     gma_method_get_cells
    96 } gma_method_compute_value_t;
    97 
    98 // these take an argument and operate on the band in-place
    99 typedef enum {
    100     gma_method_assign,
    101     gma_method_add,
    102     gma_method_subtract,
    103     gma_method_multiply,
    104     gma_method_divide,
    105     gma_method_modulus,
    106     gma_method_map
    107 } gma_method_with_arg_t;
    108 
    109 // these take an argument band and optionally another argument and operate on the band in-place
    110 typedef enum {
    111     gma_method_assign_band,
    112     gma_method_add_band,
    113     gma_method_subtract_band,
    114     gma_method_multiply_by_band,
    115     gma_method_divide_by_band,
    116     gma_method_modulus_by_band,
    117     gma_method_zonal_min,
    118     gma_method_zonal_max,
    119     gma_method_set_zonal_min,
    120     gma_method_rim_by8,
    121     gma_method_depression_pour_elevation,
    122     gma_method_fill_dem,
    123     gma_method_D8,
    124     gma_method_route_flats,
    125     gma_method_depressions,
    126     gma_method_upstream_area,
    127     gma_method_catchment
    128 } gma_two_bands_method_t;
     32// The C++ API (these are all interface classes, so everything is virtual as the actual code is in hidden template classes
     33
     34class gma_object_t {
     35public:
     36    virtual ~gma_object_t() {};
     37    virtual gma_class_t get_class() {return gma_object;};
     38    virtual gma_object_t *clone() {};
     39};
     40
     41class gma_number_t : public gma_object_t {
     42public:
     43    virtual gma_class_t get_class() {return gma_number;};
     44    virtual void set_value(double value) {};
     45    virtual void set_value(int value) {};
     46    virtual int value_as_int() {};
     47    virtual double value_as_double() {};
     48    virtual gma_number_t *clone() {};
     49    virtual void set_inf(int inf) {}; // -1 to minus inf, 0 to not inf, 1 to plus inf
     50    virtual bool is_inf() {};
     51    virtual bool is_integer() {};
     52    virtual bool is_float() {};
     53};
     54
     55class gma_pair_t : public gma_object_t {
     56public:
     57    virtual gma_class_t get_class() {return gma_pair;};
     58    virtual void set_first(gma_object_t *first) {};
     59    virtual void set_second(gma_object_t *second) {};   
     60    virtual gma_object_t *first() {};
     61    virtual gma_object_t *second() {};
     62};
     63
     64class gma_bins_t : public gma_object_t {
     65public:
     66    virtual gma_class_t get_class() {return gma_bins;};
     67    virtual unsigned int size() {};
     68    virtual void push(int value) {};
     69    virtual void push(double value) {};
     70};
     71
     72class gma_histogram_t : public gma_object_t {
     73public:
     74    virtual gma_class_t get_class() {return gma_histogram;};
     75    virtual unsigned int size() {};
     76    virtual gma_object_t *at(unsigned int i) {};
     77};
     78
     79class gma_classifier_t : public gma_object_t {
     80public:
     81    virtual gma_class_t get_class() {return gma_classifier;};
     82    virtual void add_class(gma_number_t *interval_max, gma_number_t *value) {};
     83    virtual unsigned int size() {};
     84    virtual gma_object_t *at(unsigned int i) {};
     85};
     86
     87class gma_cell_t  : public gma_object_t {
     88public:
     89    virtual gma_class_t get_class() {return gma_cell;};
     90    virtual int& x() {};
     91    virtual int& y() {};
     92    virtual void set_value(double value) {};
     93    virtual void set_value(int value) {};
     94    virtual int value_as_int() {};
     95    virtual double value_as_double() {};
     96};
     97
     98/*
     99  Return value 0 interrupts, 1 denotes ok, and 2 denotes ok and a need
     100  to save the cell value back to band.
     101*/
     102typedef int (*gma_cell_callback_f)(gma_cell_t*, gma_object_t*);
     103
     104class gma_cell_callback_t : public gma_object_t {
     105public:
     106    virtual gma_class_t get_class() {return gma_cell_callback;};
     107    virtual void set_callback(gma_cell_callback_f callback) {};
     108    virtual void set_user_data(gma_object_t*) {};
     109};
     110
     111class gma_logical_operation_t  : public gma_object_t {
     112public:
     113    virtual gma_class_t get_class() {return gma_logical_operation;};
     114    virtual void set_operation(gma_operator_t) {};
     115    virtual void set_value(int value) {};
     116    virtual void set_value(double value) {};
     117};
     118
     119class gma_hash_t : public gma_object_t {
     120public:
     121    virtual gma_class_t get_class() {return gma_hash;};
     122    virtual int size() {};
     123    virtual std::vector<gma_number_t*> *keys_sorted() {};
     124    virtual gma_object_t *get(gma_number_t *key) {};
     125};
     126
     127class gma_band_t : public gma_object_t {
     128public:
     129    virtual gma_class_t get_class() {return gma_band;};
     130    virtual GDALDataType gdal_datatype() {};
     131    virtual gma_number_t *new_number(int value) {};
     132
     133    virtual void print() {};
     134    virtual void rand() {};
     135    virtual void abs() {};
     136    virtual void exp() {};
     137    virtual void log() {};
     138    virtual void log10() {};
     139    virtual void sqrt() {};
     140    virtual void sin() {};
     141    virtual void cos() {};
     142    virtual void tan() {};
     143    virtual void ceil() {};
     144    virtual void floor() {};
     145
     146    virtual void assign(int value) {};
     147    virtual void assign_all(int value) {};
     148    virtual void add(int summand) {};
     149    virtual void subtract(int) {};
     150    virtual void multiply(int) {};
     151    virtual void divide(int) {};
     152    virtual void modulus(int divisor) {};
     153   
     154    virtual void assign(double value) {};
     155    virtual void assign_all(double value) {};
     156    virtual void add(double summand) {};
     157    virtual void subtract(double) {};
     158    virtual void multiply(double) {};
     159    virtual void divide(double) {};
     160
     161    virtual void classify(gma_classifier_t*) {};
     162    virtual void cell_callback(gma_cell_callback_t*) {};
     163
     164    // arg = NULL, pair:(n,pair:(min,max)), or bins; returns histogram
     165    virtual gma_histogram_t *histogram(gma_object_t *arg = NULL) {};
     166    // returns hash of a hashes, keys are zone numbers
     167    virtual gma_hash_t *zonal_neighbors() {};
     168    virtual gma_number_t *get_min() {};
     169    virtual gma_number_t *get_max() {};
     170    // returns a pair of numbers
     171    virtual gma_pair_t *get_range() {};
     172    virtual std::vector<gma_cell_t*> *gma_method_get_cells() {};
     173
     174    virtual void assign(gma_band_t *) {};
     175    virtual void add(gma_band_t *summand) {};
     176    virtual void subtract(gma_band_t *) {};
     177    virtual void multiply(gma_band_t *) {};
     178    virtual void divide(gma_band_t *) {};
     179    virtual void modulus(gma_band_t *) {};
     180
     181    virtual gma_hash_t *zonal_min(gma_band_t *zones) {};
     182    virtual gma_hash_t *zonal_max(gma_band_t *zones) {};
     183
     184    virtual void rim_by8(gma_band_t *areas) {};
     185
     186    virtual void fill_depressions(gma_band_t *dem) {};
     187    virtual void D8(gma_band_t *dem) {};
     188    virtual void route_flats(gma_band_t *dem) {};
     189    virtual void upstream_area(gma_band_t *) {};
     190    virtual void catchment(gma_band_t *, gma_cell_t *) {};
     191
     192};
    129193
    130194
     
    133197== Changes ==
    134198
    135 The RFC can be implemented as methods in the !RasterBand class or as a set of C callable functions. This needs to be decided.
    136199
    137200== Drivers ==