File: grid_decimation.c

package info (click to toggle)
grass 8.4.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 277,040 kB
  • sloc: ansic: 460,798; python: 227,732; cpp: 42,026; sh: 11,262; makefile: 7,007; xml: 3,637; sql: 968; lex: 520; javascript: 484; yacc: 450; asm: 387; perl: 157; sed: 25; objc: 6; ruby: 4
file content (173 lines) | stat: -rw-r--r-- 6,668 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/****************************************************************************
 *
 * MODULE:       v.decimate
 * AUTHOR(S):    Vaclav Petras
 * PURPOSE:      Reduce the number of points in a vector map
 * COPYRIGHT:    (C) 2015 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the COPYING file that comes with GRASS
 *               for details.
 *
 *****************************************************************************/

#include "grid_decimation.h"

#include <stdlib.h>

/* max size: rows * cols < max of size_t (using 1D array) */
void grid_decimation_create(struct GridDecimation *grid_decimation, size_t rows,
                            size_t cols)
{
    grid_decimation->grid_points =
        G_calloc(rows * cols, sizeof(struct DecimationPoint *));
    grid_decimation->grid_sizes = G_calloc(rows * cols, sizeof(size_t));
    grid_decimation->rows = rows;
    grid_decimation->cols = cols;
    grid_decimation->if_add_point = NULL;
    grid_decimation->on_add_point = NULL;
    grid_decimation->if_context = NULL;
    grid_decimation->on_context = NULL;
}

void grid_decimation_destroy(struct GridDecimation *grid_decimation)
{
    /* TODO: we could also offer mode without dealloc (faster) */
    int row, col;
    size_t point, npoints;

    for (row = 0; row < grid_decimation->rows; row++) {
        for (col = 0; col < grid_decimation->cols; col++) {
            /* TODO: make index function */
            size_t index = row * grid_decimation->cols + col;

            if ((npoints = grid_decimation->grid_sizes[index])) {
                /* delete points in list */
                for (point = 0; point < npoints; point++)
                    G_free(grid_decimation->grid_points[index][point]);
                /* delete list */
                G_free(grid_decimation->grid_points[index]);
            }
        }
    }
    G_free(grid_decimation->grid_points);
    G_free(grid_decimation->grid_sizes);
}

/* TODO: use Cell_head as storage? */
void grid_decimation_create_from_region(struct GridDecimation *grid_decimation,
                                        struct Cell_head *region)
{
    grid_decimation_create(grid_decimation, region->rows, region->cols);
    grid_decimation_set_region(grid_decimation, region->west, region->east,
                               region->south, region->north, region->ew_res,
                               region->ns_res);
}

/* TODO: change order of ns_res and ew_res to match xy */
void grid_decimation_set_region(struct GridDecimation *grid_decimation,
                                double minx, double maxx, double miny,
                                double maxy, double ew_res, double ns_res)
{
    grid_decimation->minx = minx;
    grid_decimation->maxx = maxx;
    grid_decimation->miny = miny;
    grid_decimation->maxy = maxy;
    grid_decimation->ns_res = ns_res;
    grid_decimation->ew_res = ew_res;
}

void grid_decimation_create_list_with_point(
    struct GridDecimation *grid_decimation, size_t index,
    struct DecimationPoint *point, size_t npoints UNUSED)
{
    struct DecimationPoint **point_list =
        G_malloc(1 * sizeof(struct DecimationPoint *));
    point_list[0] = point;
    grid_decimation->grid_points[index] = point_list;
    grid_decimation->grid_sizes[index] = 1;
}

void grid_decimation_add_point_to_list(struct GridDecimation *grid_decimation,
                                       size_t index,
                                       struct DecimationPoint *point,
                                       size_t npoints)
{
    /* TODO: this might be too much reallocation */
    /* TODO: line_ptns struct could be reused, it is not meant for this but it
     * would work */
    struct DecimationPoint **point_list =
        G_realloc(grid_decimation->grid_points[index],
                  (npoints + 1) * sizeof(struct DecimationPoint *));

    point_list[npoints] = point;
    grid_decimation->grid_points[index] = point_list;
    grid_decimation->grid_sizes[index] = npoints + 1;
}

static size_t
grid_decimation_xy_to_index(struct GridDecimation *grid_decimation, double x,
                            double y)
{
    /* TODO: test x, y */
    int row = (y - grid_decimation->miny) / grid_decimation->ns_res;
    int col = (x - grid_decimation->minx) / grid_decimation->ew_res;

    if (row < 0 || row > grid_decimation->rows || col < 0 ||
        col > grid_decimation->cols) {
        G_fatal_error(
            "Row (%d) or column (%d) outside of range (0 - %d, 0 - %d)", row,
            col, grid_decimation->rows, grid_decimation->cols);
    }
    size_t index = row * grid_decimation->cols + col;

    /* TODO: are the tests really needed, especially the second one? */
    if (row * grid_decimation->cols + col >
        grid_decimation->rows * grid_decimation->cols) {
        G_fatal_error("Index (%d) out of range (max: %d)",
                      row * grid_decimation->cols + col,
                      grid_decimation->rows * grid_decimation->cols);
    }
    return index;
}

void grid_decimation_try_add_point(struct GridDecimation *grid_decimation,
                                   int cat, double x, double y, double z,
                                   void *point_data)
{
    size_t index = grid_decimation_xy_to_index(grid_decimation, x, y);
    int npoints = grid_decimation->grid_sizes[index];

    /* TODO: when max is 1, we don't have to store the point at all */
    if (grid_decimation->max_points && grid_decimation->max_points == npoints)
        return;

    struct DecimationPoint *point = G_malloc(sizeof(struct DecimationPoint));

    point->cat = cat;
    point->x = x;
    point->y = y;
    point->z = z;

    if (!npoints) {
        grid_decimation_create_list_with_point(grid_decimation, index, point,
                                               npoints);
        if (grid_decimation->on_add_point)
            grid_decimation->on_add_point(point, point_data,
                                          grid_decimation->on_context);
    }
    else {
        if (grid_decimation->if_add_point(
                point, point_data, grid_decimation->grid_points[index], npoints,
                grid_decimation->if_context)) {
            grid_decimation_add_point_to_list(grid_decimation, index, point,
                                              npoints);
            if (grid_decimation->on_add_point)
                grid_decimation->on_add_point(point, point_data,
                                              grid_decimation->on_context);
        }
        else {
            G_free(point);
        }
    }
}