-
Notifications
You must be signed in to change notification settings - Fork 0
/
focalmaxfilter.c
147 lines (127 loc) · 5.83 KB
/
focalmaxfilter.c
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
#include "bathymetrictools.h"
/*
* This file contains:
* - Shoal buffering function
* - Essentially a 3 x 3 cell focal maximum filter
*/
/*
* Buffers shoals by one cell to all directions.
* - Used to expand shoals to ensure the safety of depth contours
* - Uses a 3 x 3 cell focal maximum filter:
*
* + + +
* + X +
* + + +
*
* - Cell X gets the shoalest value of neighborhood
* - Neighborhood is marked with "+"
* - If X is shoalest, cell value doesn't change
*/
void maxFilterSurface(struct FloatSurface *src) {
printf("Buffering shoals..");
fflush(stdout);
float nodata = src->nodata;
float max_elev = -15000.0; // Placeholder for shoalest depth
const float placeholder = max_elev;
int lenlist = 8;
float neighborhood[lenlist];
// Create new float** (2D) array:
float **temp = createFloatArray(src->cols, src->rows);
// Make a temporary copy of the original data array:
for (int row = 0; row < src->rows; row++) {
for (int col = 0; col < src->cols; col++) {
temp[row][col] = src->array[row][col];
}
}
// Iterate over cells and filter surface:
for (int row = 0; row < src->rows; row++) {
for (int col = 0; col < src->cols; col++) {
// Reset max_elev to placeholder value:
max_elev = placeholder;
// Initialize / reset neighborhood array:
lenlist = 8;
for (int i = 0; i < lenlist; i++) {
neighborhood[i] = placeholder;
}
if (row == 0) { // Top row
if (col == 0) { // Top-left
neighborhood[0] = temp[row][col + 1];
neighborhood[1] = temp[row + 1][col];
neighborhood[2] = temp[row + 1][col + 1];
lenlist = 3;
} else if (col == src->cols - 1) { // Top-right
neighborhood[0] = temp[row][col - 1];
neighborhood[1] = temp[row + 1][col];
neighborhood[2] = temp[row + 1][col -1];
lenlist = 3;
} else { // Between corners
neighborhood[0] = temp[row][col - 1];
neighborhood[1] = temp[row][col + 1];
neighborhood[2] = temp[row + 1][col];
neighborhood[3] = temp[row + 1][col - 1];
neighborhood[4] = temp[row + 1][col + 1];
lenlist = 5;
}
} else if (row == src->rows - 1) { // Bottom row
if (col == 0) { // Bottom-left
neighborhood[0] = temp[row][col + 1];
neighborhood[1] = temp[row - 1][col];
neighborhood[2] = temp[row - 1][col + 1];
lenlist = 3;
} else if (col == src->cols - 1) { // Bottom-right
neighborhood[0] = temp[row][col - 1];
neighborhood[1] = temp[row - 1][col];
neighborhood[2] = temp[row - 1][col - 1];
lenlist = 3;
} else { // Between corners
neighborhood[0] = temp[row][col - 1];
neighborhood[1] = temp[row][col + 1];
neighborhood[2] = temp[row - 1][col];
neighborhood[3] = temp[row - 1][col - 1];
neighborhood[4] = temp[row - 1][col + 1];
lenlist = 5;
}
} else { // Rows in between top and bottom
if (col == 0) { // Left edge
neighborhood[0] = temp[row][col + 1];
neighborhood[1] = temp[row + 1][col];
neighborhood[2] = temp[row - 1][col];
neighborhood[3] = temp[row - 1][col + 1];
neighborhood[4] = temp[row + 1][col + 1];
lenlist = 5;
} else if (col == src->cols - 1) { // Right edge
neighborhood[0] = temp[row][col - 1];
neighborhood[1] = temp[row + 1][col];
neighborhood[2] = temp[row - 1][col];
neighborhood[3] = temp[row - 1][col - 1];
neighborhood[4] = temp[row + 1][col - 1];
lenlist = 5;
} else { // Between edges
neighborhood[0] = temp[row - 1][col - 1];
neighborhood[1] = temp[row - 1][col];
neighborhood[2] = temp[row - 1][col + 1];
neighborhood[3] = temp[row][col - 1];
neighborhood[4] = temp[row][col + 1];
neighborhood[5] = temp[row + 1][col - 1];
neighborhood[6] = temp[row + 1][col];
neighborhood[7] = temp[row + 1][col + 1];
lenlist = 8;
}
}
// Get max elevation (shoalest depth):
for (int i = 0; i < lenlist; i++) {
if (neighborhood[i] > max_elev) {
max_elev = neighborhood[i];
}
}
// Update source array cell values if max_elev is shoaler and max_elev is not nodata:
if (max_elev > src->array[row][col] && fabs(max_elev - nodata) > EPSILON && fabs(src->array[row][col] - nodata) > EPSILON) {
src->array[row][col] = max_elev;
}
}
}
// Free temporary data array
freeFloatArray(temp, src->rows);
printf("Done\n");
fflush(stdout);
}