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