1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Tool Library //
9 // Grid_Tools //
10 // //
11 //-------------------------------------------------------//
12 // //
13 // Grid_Shrink_Expand.cpp //
14 // //
15 // Copyright (C) 2011 by //
16 // Volker Wichmann and Olaf Conrad //
17 // //
18 //-------------------------------------------------------//
19 // //
20 // This file is part of 'SAGA - System for Automated //
21 // Geoscientific Analyses'. SAGA is free software; you //
22 // can redistribute it and/or modify it under the terms //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the //
25 // License, or (at your option) any later version. //
26 // //
27 // SAGA is distributed in the hope that it will be //
28 // useful, but WITHOUT ANY WARRANTY; without even the //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A //
30 // PARTICULAR PURPOSE. See the GNU General Public //
31 // License for more details. //
32 // //
33 // You should have received a copy of the GNU General //
34 // Public License along with this program; if not, see //
35 // <http://www.gnu.org/licenses/>. //
36 // //
37 //-------------------------------------------------------//
38 // //
39 // e-mail: wichmann@laserdata //
40 // //
41 // contact: Volker Wichmann //
42 // LASERDATA GmbH //
43 // Management and analysis of //
44 // laserscanning data //
45 // Innsbruck, Austria //
46 // //
47 ///////////////////////////////////////////////////////////
48
49 //---------------------------------------------------------
50 #include "Grid_Shrink_Expand.h"
51
52
53 ///////////////////////////////////////////////////////////
54 // //
55 // //
56 // //
57 ///////////////////////////////////////////////////////////
58
59 //---------------------------------------------------------
60 enum
61 {
62 EXPAND_MIN = 0,
63 EXPAND_MAX,
64 EXPAND_MEAN,
65 EXPAND_MAJORITY
66 };
67
68
69 ///////////////////////////////////////////////////////////
70 // //
71 // //
72 // //
73 ///////////////////////////////////////////////////////////
74
75 //---------------------------------------------------------
CGrid_Shrink_Expand(void)76 CGrid_Shrink_Expand::CGrid_Shrink_Expand(void)
77 {
78 //-----------------------------------------------------
79 Set_Name (_TL("Shrink and Expand"));
80
81 Set_Author ("V.Wichmann & O.Conrad (c) 2011");
82
83 Set_Description (_TW(
84 "The tool allows one to shrink or expand regions with valid data by a certain distance (defined by the kernel radius). "
85 "Shrinking just invalidates cells with valid data at the border to No Data regions, expanding sets No Data "
86 "cells along the border of regions with valid data to a new valid value. The tool provides several options "
87 "how to calculate this new value: minimum, maximum, mean or majority of the valid cells within the kernel.\n\n"
88 ));
89
90 //-----------------------------------------------------
91 Parameters.Add_Grid("",
92 "INPUT" , _TL("Grid"),
93 _TL("The input grid."),
94 PARAMETER_INPUT
95 );
96
97 Parameters.Add_Grid("",
98 "RESULT" , _TL("Result Grid"),
99 _TL("The output grid."),
100 PARAMETER_OUTPUT_OPTIONAL
101 );
102
103 Parameters.Add_Choice("",
104 "OPERATION" , _TL("Operation"),
105 _TL("Choose the type of operation."),
106 CSG_String::Format("%s|%s|%s|%s",
107 _TL("shrink" ),
108 _TL("expand" ),
109 _TL("shrink and expand"),
110 _TL("expand and shrink")
111 ), 3
112 );
113
114 Parameters.Add_Choice("",
115 "CIRCLE" , _TL("Search Mode"),
116 _TL("Choose the shape of the kernel."),
117 CSG_String::Format("%s|%s",
118 _TL("Square"),
119 _TL("Circle")
120 ), 1
121 );
122
123 Parameters.Add_Int("",
124 "RADIUS" , _TL("Radius"),
125 _TL("The kernel radius [cells]."),
126 1, 1, true
127 );
128
129 Parameters.Add_Choice("",
130 "EXPAND" , _TL("Method"),
131 _TL("Choose how to fill no-data cells."),
132 CSG_String::Format("%s|%s|%s|%s",
133 _TL("minimum" ),
134 _TL("maximum" ),
135 _TL("mean" ),
136 _TL("majority")
137 ), 3
138 );
139
140 Parameters.Add_Bool("EXPAND",
141 "KEEP_TYPE" , _TL("Preserve Data Type"),
142 _TL("If false, mean value expansion results will be stored with floating point precision."),
143 true
144 );
145 }
146
147
148 ///////////////////////////////////////////////////////////
149 // //
150 ///////////////////////////////////////////////////////////
151
152 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)153 int CGrid_Shrink_Expand::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
154 {
155 if( pParameter->Cmp_Identifier("OPERATION") )
156 {
157 pParameters->Set_Enabled("EXPAND", pParameter->asInt() > 0);
158 }
159
160 if( pParameter->Cmp_Identifier("EXPAND") )
161 {
162 pParameters->Set_Enabled("KEEP_TYPE", pParameter->asInt() == 2); // mean?!
163 }
164
165 return( CSG_Tool_Grid::On_Parameters_Enable(pParameters, pParameter) );
166 }
167
168
169 ///////////////////////////////////////////////////////////
170 // //
171 ///////////////////////////////////////////////////////////
172
173 //---------------------------------------------------------
On_Execute(void)174 bool CGrid_Shrink_Expand::On_Execute(void)
175 {
176 if( !m_Kernel.Set_Radius(Parameters("RADIUS")->asInt(), Parameters("CIRCLE")->asInt() == 0) )
177 {
178 Error_Set(_TL("could not initialize search kernel"));
179
180 return( false );
181 }
182
183 //-----------------------------------------------------
184 CSG_Grid *pInput = Parameters("INPUT" )->asGrid(), Input;
185 CSG_Grid *pResult = Parameters("RESULT")->asGrid();
186
187 if( !pResult || pResult == pInput )
188 {
189 Input.Create(*pInput);
190 pResult = pInput;
191 pInput = &Input;
192 }
193
194 //-----------------------------------------------------
195 TSG_Data_Type Type = pInput->Get_Type();
196
197 if( Parameters("OPERATION")->asInt () > 0 // expands
198 && Parameters("EXPAND" )->asInt () == 2 // mean
199 && Parameters("KEEP_TYPE")->asBool() == false // keep data type?
200 && Type != SG_DATATYPE_Float && Type != SG_DATATYPE_Double )
201 {
202 Type = SG_DATATYPE_Float;
203 }
204
205 if( pResult->Get_Type() != Type )
206 {
207 pResult->Create(Get_System(), Type);
208 pResult->Set_Name(pInput->Get_Name());
209 }
210
211 //-----------------------------------------------------
212 switch( Parameters("OPERATION")->asInt() )
213 {
214 case 0: // shrink
215 {
216 Do_Shrink(pInput, pResult);
217 }
218 break;
219
220 case 1: // expand
221 {
222 Do_Expand(pInput, pResult);
223 }
224 break;
225
226 case 2: // shrink and expand
227 {
228 CSG_Grid TMP(pResult);
229
230 Do_Shrink(pInput, &TMP);
231 Do_Expand(&TMP , pResult);
232 }
233 break;
234
235 default: // expand and shrink
236 {
237 CSG_Grid TMP(pResult);
238
239 Do_Expand(pInput, &TMP);
240 Do_Shrink(&TMP , pResult);
241 }
242 break;
243 }
244
245 //-----------------------------------------------------
246 if( pResult == Parameters("INPUT")->asGrid() )
247 {
248 DataObject_Update(pResult);
249 }
250 else switch( Parameters("OPERATION")->asInt() )
251 {
252 case 0: pResult->Fmt_Name("%s [%s]", pInput->Get_Name(), _TL("Shrink" )); break;
253 case 1: pResult->Fmt_Name("%s [%s]", pInput->Get_Name(), _TL("Expand" )); break;
254 case 2: pResult->Fmt_Name("%s [%s]", pInput->Get_Name(), _TL("Shrink and Expand")); break;
255 default: pResult->Fmt_Name("%s [%s]", pInput->Get_Name(), _TL("Expand and Shrink")); break;
256 }
257
258 m_Kernel.Destroy();
259
260 return( true );
261 }
262
263
264 ///////////////////////////////////////////////////////////
265 // //
266 ///////////////////////////////////////////////////////////
267
268 //---------------------------------------------------------
Do_Shrink(CSG_Grid * pInput,CSG_Grid * pResult)269 bool CGrid_Shrink_Expand::Do_Shrink(CSG_Grid *pInput, CSG_Grid *pResult)
270 {
271 m_pInput = pInput;
272
273 Process_Set_Text("%s...", _TL("Shrink"));
274
275 for(int y=0; y<Get_NY() && Set_Progress(y); y++)
276 {
277 #pragma omp parallel for
278 for(int x=0; x<Get_NX(); x++)
279 {
280 bool bShrink = m_pInput->is_NoData(x, y);
281
282 for(int i=0; !bShrink && i<m_Kernel.Get_Count(); i++)
283 {
284 int ix = m_Kernel.Get_X(i, x);
285 int iy = m_Kernel.Get_Y(i, y);
286
287 if( is_InGrid(ix, iy) && m_pInput->is_NoData(ix, iy) )
288 {
289 bShrink = true;
290 }
291 }
292
293 if( bShrink )
294 {
295 pResult->Set_NoData(x, y);
296 }
297 else
298 {
299 pResult->Set_Value(x, y, m_pInput->asDouble(x, y));
300 }
301 }
302 }
303
304 return( true );
305 }
306
307
308 ///////////////////////////////////////////////////////////
309 // //
310 ///////////////////////////////////////////////////////////
311
312 //---------------------------------------------------------
Do_Expand(CSG_Grid * pInput,CSG_Grid * pResult)313 bool CGrid_Shrink_Expand::Do_Expand(CSG_Grid *pInput, CSG_Grid *pResult)
314 {
315 m_pInput = pInput;
316
317 Process_Set_Text("%s...", _TL("Expand"));
318
319 int Method = Parameters("EXPAND")->asInt();
320
321 for(int y=0; y<Get_NY() && Set_Progress(y); y++)
322 {
323 #pragma omp parallel for
324 for(int x=0; x<Get_NX(); x++)
325 {
326 double Value;
327
328 if( Get_Expand_Value(x, y, Method, Value) )
329 {
330 pResult->Set_Value(x, y, Value);
331 }
332 else
333 {
334 pResult->Set_NoData(x, y);
335 }
336 }
337 }
338
339 return( true );
340 }
341
342
343 ///////////////////////////////////////////////////////////
344 // //
345 ///////////////////////////////////////////////////////////
346
347 //---------------------------------------------------------
Get_Expand_Value(int x,int y,int Method,double & Value)348 bool CGrid_Shrink_Expand::Get_Expand_Value(int x, int y, int Method, double &Value)
349 {
350 if( !m_pInput->is_NoData(x, y) )
351 {
352 Value = m_pInput->asDouble(x, y);
353
354 return( true );
355 }
356
357 //-----------------------------------------------------
358 if( Method == EXPAND_MAJORITY )
359 {
360 CSG_Unique_Number_Statistics Majority;
361
362 for(int i=0; i<m_Kernel.Get_Count(); i++)
363 {
364 int ix = m_Kernel.Get_X(i, x);
365 int iy = m_Kernel.Get_Y(i, y);
366
367 if( m_pInput->is_InGrid(ix, iy) )
368 {
369 Majority.Add_Value(m_pInput->asDouble(ix, iy));
370 }
371 }
372
373 return( Majority.Get_Majority(Value) );
374 }
375
376 //-----------------------------------------------------
377 {
378 CSG_Simple_Statistics Statistics;
379
380 for(int i=0; i<m_Kernel.Get_Count(); i++)
381 {
382 int ix = m_Kernel.Get_X(i, x);
383 int iy = m_Kernel.Get_Y(i, y);
384
385 if( m_pInput->is_InGrid(ix, iy) )
386 {
387 Statistics.Add_Value(m_pInput->asDouble(ix, iy));
388 }
389 }
390
391 if( Statistics.Get_Count() > 0 )
392 {
393 switch( Method )
394 {
395 default:
396 case EXPAND_MEAN: Value = Statistics.Get_Mean (); break;
397 case EXPAND_MIN : Value = Statistics.Get_Minimum(); break;
398 case EXPAND_MAX : Value = Statistics.Get_Maximum(); break;
399 }
400
401 return( true );
402 }
403 }
404
405 return( false );
406 }
407
408
409 ///////////////////////////////////////////////////////////
410 // //
411 // //
412 // //
413 ///////////////////////////////////////////////////////////
414
415 //---------------------------------------------------------
416