1 /**********************************************************
2 * Version $Id$
3 *********************************************************/
4
5 ///////////////////////////////////////////////////////////
6 // //
7 // SAGA //
8 // //
9 // System for Automated Geoscientific Analyses //
10 // //
11 // Tool Library //
12 // grid_analysis //
13 // //
14 //-------------------------------------------------------//
15 // //
16 // Grid_Iterative_Truncation.cpp //
17 // //
18 // Copyright (C) 2020 by //
19 // Volker Wichmann //
20 // //
21 //-------------------------------------------------------//
22 // //
23 // This file is part of 'SAGA - System for Automated //
24 // Geoscientific Analyses'. SAGA is free software; you //
25 // can redistribute it and/or modify it under the terms //
26 // of the GNU General Public License as published by the //
27 // Free Software Foundation, either version 2 of the //
28 // License, or (at your option) any later version. //
29 // //
30 // SAGA is distributed in the hope that it will be //
31 // useful, but WITHOUT ANY WARRANTY; without even the //
32 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
33 // PARTICULAR PURPOSE. See the GNU General Public //
34 // License for more details. //
35 // //
36 // You should have received a copy of the GNU General //
37 // Public License along with this program; if not, see //
38 // <http://www.gnu.org/licenses/>. //
39 // //
40 //-------------------------------------------------------//
41 // //
42 // e-mail: wichmann@laserdata //
43 // //
44 // contact: Volker Wichmann //
45 // LASERDATA GmbH //
46 // Management and analysis of //
47 // laserscanning data //
48 // Innsbruck, Austria //
49 // //
50 ///////////////////////////////////////////////////////////
51
52 //---------------------------------------------------------
53
54
55 ///////////////////////////////////////////////////////////
56 // //
57 // //
58 // //
59 ///////////////////////////////////////////////////////////
60
61 //---------------------------------------------------------
62 #include "Grid_Iterative_Truncation.h"
63
64
65 ///////////////////////////////////////////////////////////
66 // //
67 // //
68 // //
69 ///////////////////////////////////////////////////////////
70
71 //-----------------------------------------------------------
CGrid_Iterative_Truncation(void)72 CGrid_Iterative_Truncation::CGrid_Iterative_Truncation(void)
73 {
74 Set_Name (_TL("Iterative Truncation"));
75
76 Set_Author ("V. Wichmann (c) 2020");
77
78 Parameters.Set_Description(_TW(
79 "The tool allows one to perform an iterative truncation to a target average. This operation "
80 "iteratively removes the highest values from the input grid until the average of all grid values "
81 "matches the user-specified target average. Instead of simply removing the highest cell values, "
82 "these values can also be replaced by a substitute value.\n"
83 "An example application is surface soil cleanup, where the highest soil contaminant concentrations "
84 "are removed until targeted post-remediation concentrations are reached. In this case, the "
85 "substitute value would be set to the concentration of clean fill.\n\n"
86 ));
87
88
89 Parameters.Add_Grid("",
90 "INPUT" , _TL("Input"),
91 _TL("Grid to analyse."),
92 PARAMETER_INPUT
93 );
94
95 Parameters.Add_Grid("",
96 "REMOVED" , _TL("Removed Cells"),
97 _TL("Output grid showing the removed cells (1/NoData)."),
98 PARAMETER_OUTPUT, true, SG_DATATYPE_Char
99 );
100
101 Parameters.Add_Grid("",
102 "OUTPUT" , _TL("Output"),
103 _TL("The modified input grid."),
104 PARAMETER_OUTPUT_OPTIONAL
105 );
106
107 Parameters.Add_Double("",
108 "TARGET", _TL("Target Average"),
109 _TL("The target average."),
110 100.0
111 );
112
113 Parameters.Add_Choice("",
114 "METHOD" , _TL("Method"),
115 _TL("Choose a mode of operation."),
116 CSG_String::Format("%s|%s",
117 _TL("remove cell values"),
118 _TL("replace cell values")
119 ), 0
120 );
121
122 Parameters.Add_Double("METHOD",
123 "SUBSTITUTE", _TL("Substitute Value"),
124 _TL("The value with which the removed cell values are replaced."),
125 0.0
126 );
127 }
128
129
130 ///////////////////////////////////////////////////////////
131 // //
132 ///////////////////////////////////////////////////////////
133
134 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)135 int CGrid_Iterative_Truncation::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
136 {
137 if( pParameter->Cmp_Identifier("METHOD") )
138 {
139 pParameters->Set_Enabled("SUBSTITUTE", pParameter->asInt() == 1);
140 }
141
142 return( 1 );
143 }
144
145
146 ///////////////////////////////////////////////////////////
147 // //
148 ///////////////////////////////////////////////////////////
149
150 //---------------------------------------------------------
On_Execute(void)151 bool CGrid_Iterative_Truncation::On_Execute(void)
152 {
153
154 CSG_Grid *pInput = Parameters("INPUT")->asGrid();
155 CSG_Grid *pRemoved = Parameters("REMOVED")->asGrid();
156 CSG_Grid *pOutput = Parameters("OUTPUT")->asGrid();
157 double dTarget = Parameters("TARGET")->asDouble();
158 int iMethod = Parameters("METHOD")->asInt();
159 double dSubstitute = Parameters("SUBSTITUTE")->asDouble();
160 double dSum = 0.0;
161 sLong iCells = 0;
162
163
164 //-------------------------------------------------
165 pRemoved->Assign_NoData();
166
167 if( pOutput != NULL )
168 {
169 pOutput->Assign(pInput);
170 }
171
172 //-------------------------------------------------
173 for(int y=0; y<Get_NY() && Set_Progress(y); y++)
174 {
175 for(int x=0; x<Get_NX(); x++)
176 {
177 if( !pInput->is_NoData(x, y) )
178 {
179 dSum += pInput->asDouble(x, y);
180 iCells++;
181 }
182 }
183 }
184
185
186 //-------------------------------------------------
187 if( !pInput->Set_Index() )
188 {
189 Error_Set(_TL("index creation failed"));
190
191 return( false );
192 }
193
194 int x, y;
195 double dAverage = dSum / iCells;
196 bool bReached = false;
197
198 Message_Fmt("\n%s: %.2f", _TL("Average of input grid"), dAverage);
199
200
201 //-------------------------------------------------
202 for(sLong n=0; n<Get_NCells() && Set_Progress_NCells(n); n++)
203 {
204 if( dAverage <= dTarget )
205 {
206 Message_Fmt("\n%s: %.2f", _TL("Target average reached"), dAverage);
207 bReached = true;
208 break;
209 }
210
211 if( pInput->Get_Sorted(n, x, y) )
212 {
213 pRemoved->Set_Value(x, y, 1.0);
214
215 switch (iMethod)
216 {
217 default:
218 case 0:
219 {
220 if( pOutput != NULL )
221 {
222 pOutput->Set_NoData(x, y);
223 }
224
225 dSum -= pInput->asDouble(x, y);
226 iCells--;
227 break;
228 }
229 case 1:
230 {
231 if( pOutput != NULL )
232 {
233 pOutput->Set_Value(x, y, dSubstitute);
234 }
235
236 dSum = dSum - pInput->asDouble(x, y) + dSubstitute;
237 break;
238 }
239 }
240
241 if( iCells > 0 )
242 {
243 dAverage = dSum / iCells;
244 }
245 }
246 }
247
248
249 //-----------------------------------------------------
250 if( !bReached )
251 {
252 Message_Fmt("\n%s: %.2f", _TL("Target average NOT reached"), dAverage);
253 Error_Fmt("\n%s: %.2f", _TL("Target average NOT reached"), dAverage);
254
255 return( false );
256 }
257
258 return( true );
259 }
260
261
262 ///////////////////////////////////////////////////////////
263 // //
264 // //
265 // //
266 ///////////////////////////////////////////////////////////
267
268 //---------------------------------------------------------
269