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