1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                     Tool Library                      //
9 //                     Grid_Calculus                     //
10 //                                                       //
11 //-------------------------------------------------------//
12 //                                                       //
13 //                 Grid_Random_Field.cpp                 //
14 //                                                       //
15 //                 Copyright (C) 2005 by                 //
16 //                      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:     oconrad@saga-gis.org                   //
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Goettingen               //
44 //                Goldschmidtstr. 5                      //
45 //                37077 Goettingen                       //
46 //                Germany                                //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include "Grid_Random_Field.h"
52 
53 
54 ///////////////////////////////////////////////////////////
55 //														 //
56 //														 //
57 //														 //
58 ///////////////////////////////////////////////////////////
59 
60 //---------------------------------------------------------
CGrid_Random_Field(void)61 CGrid_Random_Field::CGrid_Random_Field(void)
62 {
63 	Set_Name		(_TL("Random Field"));
64 
65 	Set_Author		("O.Conrad (c) 2005");
66 
67 	Set_Description	(_TW(
68 		"Create a grid with pseudo-random numbers as grid cell values. "
69 	));
70 
71 	//-----------------------------------------------------
72 	Parameters.Add_Choice("",
73 		"METHOD"	, _TL("Method"),
74 		_TL(""),
75 		CSG_String::Format("%s|%s",
76 			_TL("Uniform"),
77 			_TL("Gaussian")
78 		), 1
79 	);
80 
81 	Parameters.Add_Node("",
82 		"UNIFORM"	, _TL("Uniform"),
83 		_TL("")
84 	);
85 
86 	Parameters.Add_Range("UNIFORM",
87 		"RANGE"		, _TL("Range"),
88 		_TL(""),
89 		0., 1.
90 	);
91 
92 	Parameters.Add_Node("",
93 		"GAUSSIAN"	, _TL("Gaussian"),
94 		_TL("")
95 	);
96 
97 	Parameters.Add_Double("GAUSSIAN",
98 		"MEAN"		, _TL("Arithmetic Mean"),
99 		_TL(""),
100 		0.
101 	);
102 
103 	Parameters.Add_Double("GAUSSIAN",
104 		"STDDEV"	, _TL("Standard Deviation"),
105 		_TL(""),
106 		1., 0., true
107 	);
108 
109 	//-----------------------------------------------------
110 	m_Grid_Target.Create(&Parameters, false, "", "TARGET_");
111 
112 	m_Grid_Target.Add_Grid("OUT_GRID", _TL("Random Field"), false);
113 }
114 
115 
116 ///////////////////////////////////////////////////////////
117 //														 //
118 ///////////////////////////////////////////////////////////
119 
120 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)121 int CGrid_Random_Field::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
122 {
123 	if( pParameter->Cmp_Identifier("METHOD") )
124 	{
125 		pParameters->Set_Enabled("UNIFORM" , pParameter->asInt() == 0);
126 		pParameters->Set_Enabled("GAUSSIAN", pParameter->asInt() == 1);
127 	}
128 
129 	m_Grid_Target.On_Parameters_Enable(pParameters, pParameter);
130 
131 	return( CSG_Tool::On_Parameters_Enable(pParameters, pParameter) );
132 }
133 
134 
135 ///////////////////////////////////////////////////////////
136 //														 //
137 ///////////////////////////////////////////////////////////
138 
139 //---------------------------------------------------------
On_Execute(void)140 bool CGrid_Random_Field::On_Execute(void)
141 {
142 	//-----------------------------------------------------
143 	CSG_Grid	*pGrid	= m_Grid_Target.Get_Grid("OUT_GRID");
144 
145 	if( !pGrid )
146 	{
147 		return( false );
148 	}
149 
150 	//-----------------------------------------------------
151 	int		Method	= Parameters("METHOD")->asInt();
152 
153 	double	a	= Method == 0
154 		? Parameters("RANGE" )->asRange()->Get_Min()
155 		: Parameters("MEAN"  )->asDouble();
156 
157 	double	b	= Method == 0
158 		? Parameters("RANGE" )->asRange()->Get_Max()
159 		: Parameters("STDDEV")->asDouble();
160 
161 	//-----------------------------------------------------
162 	for(int y=0; y<pGrid->Get_NY() && Set_Progress(y, pGrid->Get_NY()); y++)
163 	{
164 		#pragma omp parallel for
165 		for(int x=0; x<pGrid->Get_NX(); x++)
166 		{
167 			switch( Method )
168 			{
169 			case 0:	// uniform...
170 				pGrid->Set_Value(x, y, CSG_Random::Get_Uniform (a, b));
171 				break;
172 
173 			case 1:	// gaussian...
174 				pGrid->Set_Value(x, y, CSG_Random::Get_Gaussian(a, b));
175 				break;
176 			}
177 		}
178 	}
179 
180 	//-----------------------------------------------------
181 	return( true );
182 }
183 
184 
185 ///////////////////////////////////////////////////////////
186 //														 //
187 //														 //
188 //														 //
189 ///////////////////////////////////////////////////////////
190 
191 //---------------------------------------------------------
CGrid_Fractal_Brownian_Noise(void)192 CGrid_Fractal_Brownian_Noise::CGrid_Fractal_Brownian_Noise(void)
193 {
194 	Set_Name		(_TL("Fractal Brownian Noise"));
195 
196 	Set_Author		("A.Jack, O.Conrad (c) 2017");
197 
198 	Set_Description	(_TW(
199 		"This tool uses uniform random to create a grid that resembles fractal Brownian noise (FBN). "
200 		"The advantage of FBN noise is that it appears to have texture to the human eye, that resembles "
201 		"the types of textures that are observed in nature; terrains, algae growth, clouds, etc. "
202 		"The degree of texture observed in the FBN grid is dependent upon the sizes of the wavelengths chosen. "
203 		"The wavelengths should be chosen so they increase in size (a doubling of successive wavelengths "
204 		"is a good point to start). The greater the magnitude of the \"ramp\" of successive wavelengths the "
205 		"greater the texture in the FBN grid. "
206 	));
207 
208 	//-----------------------------------------------------
209 	Parameters.Add_Choice("",
210 		"SCALING"	, _TL("Scaling"),
211 		_TL(""),
212 		CSG_String::Format("%s|%s",
213 			_TL("linear"),
214 			_TL("geometric")
215 		), 1
216 	);
217 
218 	Parameters.Add_Double("",
219 		"MAX_SCALE"	, _TL("Maximum Scale"),
220 		_TL(""),
221 		1., 0., true
222 	);
223 
224 	Parameters.Add_Int("",
225 		"STEPS"		, _TL("Steps"),
226 		_TL(""),
227 		8, 1, true
228 	);
229 
230 	Parameters.Add_Range("",
231 		"RANGE"		, _TL("Noise Range"),
232 		_TL(""),
233 		-1., 1.
234 	);
235 
236 	//-----------------------------------------------------
237 	m_Grid_Target.Create(&Parameters, false, "", "TARGET_");
238 
239 	m_Grid_Target.Add_Grid("OUT_GRID", _TL("Fractal Brownian Noise"), false);
240 }
241 
242 
243 ///////////////////////////////////////////////////////////
244 //														 //
245 ///////////////////////////////////////////////////////////
246 
247 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter)248 int CGrid_Fractal_Brownian_Noise::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
249 {
250 	if( pParameter->Cmp_Identifier("SYSTEM") )
251 	{
252 		CSG_Grid_System	System(*pParameter->asGrid_System());
253 
254 		if( System.is_Valid() )
255 		{
256 			double	d	= 0.5 * SG_Get_Length(System.Get_XRange(), System.Get_YRange());
257 
258 			pParameters->Set_Parameter("MAX_SCALE", System.Get_Cellsize() * (int)(d / System.Get_Cellsize()));
259 		}
260 	}
261 
262 	return( CSG_Tool::On_Parameter_Changed(pParameters, pParameter) );
263 }
264 
265 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)266 int CGrid_Fractal_Brownian_Noise::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
267 {
268 	m_Grid_Target.On_Parameters_Enable(pParameters, pParameter);
269 
270 	return( CSG_Tool::On_Parameters_Enable(pParameters, pParameter) );
271 }
272 
273 
274 ///////////////////////////////////////////////////////////
275 //														 //
276 ///////////////////////////////////////////////////////////
277 
278 //---------------------------------------------------------
On_Execute(void)279 bool CGrid_Fractal_Brownian_Noise::On_Execute(void)
280 {
281 	//-----------------------------------------------------
282 	CSG_Grid	*pGrid	= m_Grid_Target.Get_Grid("OUT_GRID");
283 
284 	if( !pGrid )
285 	{
286 		return( false );
287 	}
288 
289 	pGrid->Assign(0.);
290 	pGrid->Set_Name(_TL("Fractal Brownian Noise"));
291 
292 	int		Scaling		= Parameters("SCALING"  )->asInt   ();
293 	int		nSteps		= Parameters("STEPS"    )->asInt   ();
294 	double	maxScale	= Parameters("MAX_SCALE")->asDouble();
295 
296 	if( maxScale < pGrid->Get_Cellsize() )
297 	{
298 		Error_Set(_TL("maximum scale must be greater than the cell size"));
299 
300 		return( false );
301 	}
302 
303 	double	Scale, dScale, Offset;
304 
305 	Scale	= pGrid->Get_Cellsize();
306 
307 	switch( Scaling )
308 	{
309 	default:	dScale	=        (maxScale - Scale) / nSteps ;	break;	// linear
310 	case  1:	dScale	= exp(log(maxScale / Scale) / nSteps);	break;	// geometric
311 	}
312 
313 	//-----------------------------------------------------
314 	for(int i=0; i<=nSteps && Set_Progress(i, nSteps); i++)
315 	{
316 		Message_Fmt("\n%s: [%d] %f", _TL("Scale"), i, Scale);
317 
318 		Add_Noise(pGrid, Scale);
319 
320 		switch( Scaling )
321 		{
322 		default:	Scale	+= dScale;	break;	// linear
323 		case  1:	Scale	*= dScale;	break;	// geometric
324 		}
325 	}
326 
327 	//-----------------------------------------------------
328 	Offset	= Parameters("RANGE")->asRange()->Get_Min();
329 	Scale	= Parameters("RANGE")->asRange()->Get_Max() - Offset;
330 
331 	if( Scale <= 0. || pGrid->Get_Range() <= 0. )
332 	{
333 		Error_Set(_TL("grid value and noise range must be greater than zero"));
334 
335 		return( false );
336 	}
337 
338 	Scale	/= pGrid->Get_Range();
339 	dScale	 = pGrid->Get_Min();
340 
341 	#pragma omp parallel for
342 	for(sLong i=0; i<pGrid->Get_NCells(); i++)
343 	{
344 		if( pGrid->is_NoData(i) == false )
345 		{
346 			pGrid->Set_Value(i, Offset + Scale * (pGrid->asDouble(i) - dScale));
347 		}
348 	}
349 
350 	return( true );
351 }
352 
353 //---------------------------------------------------------
Add_Noise(CSG_Grid * pGrid,double Scale)354 bool CGrid_Fractal_Brownian_Noise::Add_Noise(CSG_Grid *pGrid, double Scale)
355 {
356 	CSG_Grid	Noise;
357 	CSG_Rect	Extent(pGrid->Get_Extent(true));
358 
359 	Extent.Inflate(Scale, false);	// guarantee that the noise grid is always large enough, otherwise we get edge effects with larger scale values
360 
361 	if( !Noise.Create(CSG_Grid_System(Scale, Extent)) )
362 	{
363 		return( false );
364 	}
365 
366 	#pragma omp parallel for
367 	for(sLong i=0; i<Noise.Get_NCells(); i++)
368 	{
369 		Noise.Set_Value(i, CSG_Random::Get_Uniform(0, 1));
370 	}
371 
372 	#pragma omp parallel for
373 	for(int y=0; y<pGrid->Get_NY(); y++)
374 	{
375 		TSG_Point	p;
376 
377 		p.y	= pGrid->Get_YMin() + y * pGrid->Get_Cellsize();
378 		p.x	= pGrid->Get_XMin();
379 
380 		for(int x=0; x<pGrid->Get_NX(); x++, p.x+=pGrid->Get_Cellsize())
381 		{
382 			if( pGrid->is_NoData(x, y) == false )
383 			{
384 				pGrid->Add_Value(x, y, Noise.Get_Value(p));
385 			}
386 		}
387 	}
388 
389 	return( true );
390 }
391 
392 
393 ///////////////////////////////////////////////////////////
394 //														 //
395 //														 //
396 //														 //
397 ///////////////////////////////////////////////////////////
398 
399 //---------------------------------------------------------
400