/*
 * r.in.pdal point binning logic
 *
 * Copyright 2011-2015, 2020 by Markus Metz, and The GRASS Development Team
 * Authors:
 *  Markus Metz (r.in.lidar)
 *  Vaclav Petras (move code to separate functions)
 *  Maris Nartiss (refactoring for r.in.pdal)
 *
 * This program is free software licensed under the GPL (>=v2).
 * Read the COPYING file that comes with GRASS for details.
 *
 */

#ifndef __POINT_BINNING_H__
#define __POINT_BINNING_H__

#include <grass/gis.h>
#include <grass/raster.h>

/* Point binning methods: */
#define METHOD_NONE        0
#define METHOD_N           1
#define METHOD_MIN         2
#define METHOD_MAX         3
#define METHOD_RANGE       4
#define METHOD_SUM         5
#define METHOD_MEAN        6
#define METHOD_STDDEV      7
#define METHOD_VARIANCE    8
#define METHOD_COEFF_VAR   9
#define METHOD_MEDIAN     10
#define METHOD_MODE       11
#define METHOD_PERCENTILE 12
#define METHOD_SKEWNESS   13
#define METHOD_TRIMMEAN   14
#define METHOD_SIDNMAX    15
#define METHOD_SIDNMIN    16
#define METHOD_EV1        17
#define METHOD_EV2        18
#define METHOD_EV3        19


struct z_node
{
    int next;
    double z;
};

struct cnt_node
{
    int next;
    CELL value;
    int count;
};

struct com_node
{
    int n;
    double *meanx;
    double *meany;
    double *comoment;
};

struct BinIndex
{
    int num_nodes;
    int max_nodes;
    void *nodes;
};

struct PointBinning
{
    int method;

    int bin_n;
    int bin_min;
    int bin_max;
    int bin_sum;
    int bin_m2;
    int bin_z_index;
    int bin_cnt_index;
    int bin_eigenvalues;
    int bin_coordinates;

    void *n_array;
    void *min_array;
    void *max_array;
    void *sum_array;
    void *c_array;
    void *mean_array;
    void *m2_array;
    void *index_array;
    void *x_array;
    void *y_array;

    int pth;
    double trim;
};

void *get_cell_ptr(void *, int, int, int, RASTER_MAP_TYPE);
int blank_array(void *, int, int, RASTER_MAP_TYPE, int);

void point_binning_set(struct PointBinning *, char *, char *, char *);
void point_binning_allocate(struct PointBinning *, int, int, RASTER_MAP_TYPE);
void point_binning_free(struct PointBinning *, struct BinIndex *);


void write_values(struct PointBinning *,
                  struct BinIndex *, void *, int, int, RASTER_MAP_TYPE);
void update_value(struct PointBinning *,
                  struct BinIndex *, int, int,
                  int, RASTER_MAP_TYPE, double, double, double);


#endif /* __POINT_BINNING_H__ */
