SAGA API Version 9.14
Loading...
Searching...
No Matches
map_grid.cpp
Go to the documentation of this file.
1
3// //
4// SAGA //
5// //
6// System for Automated Geoscientific Analyses //
7// //
8// Application Programming Interface //
9// //
10// Library: SAGA_API //
11// //
12//-------------------------------------------------------//
13// //
14// map_grid.cpp //
15// //
16// Copyright (C) 2026 by //
17// Olaf Conrad //
18// //
19//-------------------------------------------------------//
20// //
21// This file is part of 'SAGA - System for Automated //
22// Geoscientific Analyses'. SAGA is free software; you //
23// can redistribute it and/or modify it under the terms //
24// of the GNU General Public License as published by the //
25// Free Software Foundation, either version 2 of the //
26// License, or (at your option) any later version. //
27// //
28// SAGA is distributed in the hope that it will be //
29// useful, but WITHOUT ANY WARRANTY; without even the //
30// implied warranty of MERCHANTABILITY or FITNESS FOR A //
31// PARTICULAR PURPOSE. See the GNU General Public //
32// License for more details. //
33// //
34// You should have received a copy of the GNU General //
35// Public License along with this program; if not, see //
36// <http://www.gnu.org/licenses/>. //
37// //
38//-------------------------------------------------------//
39// //
40// e-mail: oconrad@saga-gis.org //
41// //
42// contact: Olaf Conrad //
43// Institute of Geography //
44// University of Hamburg //
45// Germany //
46// //
48
49//---------------------------------------------------------
50#include "../dc_helper.h"
51
52#include "map_symbology.h"
53#include "map_legend.h"
54
55#include "map_layer.h"
56
57#include "../data_manager.h"
58
59
61// //
62// //
63// //
65
66//---------------------------------------------------------
74
75
77// //
79
80//---------------------------------------------------------
82{
84
85 //-----------------------------------------------------
86 Parameters.Add_Bool ("NODE_VALUES", "VALUES" , _TL("Show Cell Values"), _TL("Show cell values when zoomed."), false);
87 Parameters.Add_Font ("VALUES", "VALUES_FONT" , _TL("Font" ), _TL(""));
88 Parameters.Add_Double("VALUES", "VALUES_SIZE" , _TL("Size" ), _TL(""), 15, 0, true , 100., true);
89 Parameters.Add_Int ("VALUES", "VALUES_DECIMALS", _TL("Decimals" ), _TL(""), 2);
90 Parameters.Add_Choice("VALUES", "VALUES_EFFECT" , _TL("Boundary Effect" ), _TL(""), CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
91 _TL("none" ),
92 _TL("full frame" ),
93 _TL("top" ),
94 _TL("top left" ),
95 _TL("left" ),
96 _TL("bottom left" ),
97 _TL("bottom" ),
98 _TL("bottom right"),
99 _TL("right" ),
100 _TL("top right" )), 1
101 )->Set_Collapsed();
102 Parameters.Add_Color("VALUES_EFFECT", "VALUES_EFFECT_COLOR", _TL("Color"), _TL(""), SG_GET_RGB(255, 255, 255));
103
104 //-----------------------------------------------------
105 // Display...
106
107 Parameters.Add_Grid_Resampling("NODE_DISPLAY", "STRETCH_RESAMPLING", _TL("Resampling"), _TL(""), CSG_Grid_Resampling::Interpolations, CSG_Grid_Resampling::NearestNeighbour);
108
109 //-----------------------------------------------------
110 // Transparency...
111
112 Parameters.Add_Grid("TRANSPARENCY", "TRANSPARENCY_GRID", _TL("Transparency Grid"),
113 _TL("Grid values used to define transparency. Transparency will be linearly scaled from full transparency to full opacity value range. Can be combined with overall transparency."),
115 );
116
117 Parameters.Add_Double("TRANSPARENCY_GRID", "TRANSPARENCY_GRID_STRETCH.MIN", _TL("Full Transparency"), _TL(""), 0.);
118 Parameters.Add_Double("TRANSPARENCY_GRID", "TRANSPARENCY_GRID_STRETCH.MAX", _TL("Full Opacity" ), _TL(""), 0.);
119
120 //-----------------------------------------------------
121 // Shading...
122
123 Parameters.Add_Choice("NODE_DISPLAY" , "SHADING" , _TL("Shading" ), _TL(""), CSG_String::Format("%s|%s|%s", _TL("none"), _TL("traditional"), _TL("multidirectional")), 0);
124 Parameters.Add_Double("SHADING" , "SHADING_AZIMUTH", _TL("Azimuth" ), _TL("Direction of the light source, measured in degree clockwise from the North direction."), 315., 0., true, 360., true);
125 Parameters.Add_Double("SHADING" , "SHADING_HEIGHT" , _TL("Height" ), _TL("Height of the light source, measured in degree above the horizon." ), 45., 0., true, 90., true);
126 Parameters.Add_Double("SHADING" , "SHADING_EXAGG" , _TL("Exaggeration"), _TL(""), 1. );
127 Parameters.Add_Double("SHADING" , "SHADING_MIN" , _TL("Minimum" ), _TL(""), 0. );
128 Parameters.Add_Double("SHADING" , "SHADING_MAX" , _TL("Maximum" ), _TL(""), 1.5);
129
130 //-----------------------------------------------------
131 Parameters.Add_Bool ("NODE_COLORS" , "RGB_ALPHA" , _TL("Alpha Channel"), _TL(""), false);
132
133 //-----------------------------------------------------
134 Parameters.Add_Node ("NODE_COLORS" , "NODE_COMPOSITE" , _TL("RGB Composite"), _TL(""));
135 Parameters.Add_Choice("NODE_COMPOSITE" , "COMPOSITE_THIS" , _TL("This Color" ), _TL(""), CSG_String::Format("%s|%s|%s", _TL("Red"), _TL("Green"), _TL("Blue")), 0);
136 Parameters.Add_Grid ("NODE_COMPOSITE" , "COMPOSITE_R" , _TL("Red" ), _TL(""), PARAMETER_INPUT_OPTIONAL, false);
137 Parameters.Add_Grid ("NODE_COMPOSITE" , "COMPOSITE_G" , _TL("Green" ), _TL(""), PARAMETER_INPUT_OPTIONAL, false);
138 Parameters.Add_Grid ("NODE_COMPOSITE" , "COMPOSITE_B" , _TL("Blue" ), _TL(""), PARAMETER_INPUT_OPTIONAL, false);
139
140 //-----------------------------------------------------
141 if( m_pObject )
142 {
143 Parameters["TRANSPARENCY_GRID"].Get_Parent()->Set_Value((void *)&m_pObject->asGrid()->Get_System());
144
145 Parameters["COMPOSITE_R" ].Get_Parent()->Set_Value((void *)&m_pObject->asGrid()->Get_System());
146 Parameters["COMPOSITE_G" ].Get_Parent()->Set_Value((void *)&m_pObject->asGrid()->Get_System());
147 Parameters["COMPOSITE_B" ].Get_Parent()->Set_Value((void *)&m_pObject->asGrid()->Get_System());
148 }
149
150 return( true );
151}
152
153
155// //
157
158//---------------------------------------------------------
159bool CSG_Map_Grid::Parameter_Changed(CSG_Parameters &Parameters, CSG_Parameter &Parameter, int Flags)
160{
161 //-----------------------------------------------------
162 if( Flags & PARAMETER_CHECK_VALUES )
163 {
164 if( Parameter.Cmp_Identifier("TRANSPARENCY_GRID") )
165 {
166 if( Parameter.asGrid() )
167 {
168 Parameters.Set_Parameter("TRANSPARENCY_GRID_STRETCH.MIN", Parameter.asGrid()->Get_Min());
169 Parameters.Set_Parameter("TRANSPARENCY_GRID_STRETCH.MAX", Parameter.asGrid()->Get_Max());
170 }
171 }
172 }
173
174 //-----------------------------------------------------
175 if( Flags & PARAMETER_CHECK_ENABLE )
176 {
177 if( Parameter.Cmp_Identifier("SHADING") )
178 {
179 Parameters.Set_Enabled("SHADING_AZIMUTH" , Parameter.asInt() != 0);
180 Parameters.Set_Enabled("SHADING_HEIGHT" , Parameter.asInt() != 0);
181 Parameters.Set_Enabled("SHADING_EXAGG" , Parameter.asInt() != 0);
182 Parameters.Set_Enabled("SHADING_MIN" , Parameter.asInt() != 0);
183 Parameters.Set_Enabled("SHADING_MAX" , Parameter.asInt() != 0);
184 }
185
186 if( Parameter.Cmp_Identifier("COLOR_SYMBOLS") )
187 {
188 int Value = Parameter.asInt();
189
190 Parameters.Set_Enabled("NODE_COMPOSITE" , Value == CSG_Map_Symbology::COMPOSITE );
191 Parameters.Set_Enabled("STRETCH_RESAMPLING" , Value != CSG_Map_Symbology::CLASSIFIED);
192 Parameters.Set_Enabled("TRANSPARENCY_GRID" , Value != CSG_Map_Symbology::RGB );
193 Parameters.Set_Enabled("RGB_ALPHA" , Value == CSG_Map_Symbology::RGB );
194 }
195
196 if( Parameter.Cmp_Identifier("TRANSPARENCY_MODE") )
197 {
198 Parameters.Set_Enabled("TRANSPARENCY", Parameter.asInt() == 0);
199 }
200
201 if( Parameter.Cmp_Identifier("TRANSPARENCY_GRID") )
202 {
203 Parameter.Set_Children_Enabled(Parameter.asGrid() != NULL);
204 }
205
206 if( Parameter.Cmp_Identifier("VALUES") )
207 {
208 Parameters.Set_Enabled("VALUES_FONT" , Parameter.asBool());
209 Parameters.Set_Enabled("VALUES_SIZE" , Parameter.asBool());
210 Parameters.Set_Enabled("VALUES_DECIMALS" , Parameter.asBool());
211 Parameters.Set_Enabled("VALUES_EFFECT" , Parameter.asBool());
212 }
213
214 if( Parameter.Cmp_Identifier("VALUES_EFFECT") )
215 {
216 Parameters.Set_Enabled("VALUES_EFFECT_COLOR", Parameter.asInt() > 0);
217 }
218
219 if( Parameter.Cmp_Identifier("COMPOSITE_THIS") )
220 {
221 Parameters["COMPOSITE_R"].Get_Parent()->Set_Enabled(Parameter.asInt() != 0);
222 Parameters["COMPOSITE_G"].Get_Parent()->Set_Enabled(Parameter.asInt() != 1);
223 Parameters["COMPOSITE_B"].Get_Parent()->Set_Enabled(Parameter.asInt() != 2);
224 }
225 }
226
227 return( CSG_Map_Layer::Parameter_Changed(Parameters, Parameter, Flags) );
228}
229
230
232// //
234
235//---------------------------------------------------------
237{
239
240 //-----------------------------------------------------
241 return( true );
242}
243
244
246// //
248
249//---------------------------------------------------------
251{
253
254 //-----------------------------------------------------
255 _Composite_Update();
256
257 //-----------------------------------------------------
258 return( true );
259}
260
261
263// //
265
266//---------------------------------------------------------
268{
269 if( m_Parameters["COLOR_SYMBOLS"].asInt() == CSG_Map_Symbology::DISCRETE
270 || m_Parameters["COLOR_SYMBOLS"].asInt() == CSG_Map_Symbology::GRADUATED
271 || m_Parameters["COLOR_SYMBOLS"].asInt() == CSG_Map_Symbology::COMPOSITE )
272 {
273 if( m_Parameters["STRETCH"].asInt() < 3 ) // not 'manual'
274 {
275 m_Stretch_Extent = m_Parameters["STRETCH"].asInt();
276 }
277
278 //-------------------------------------------------
279 double Minimum, Maximum; _Get_Stretch_Extent(Extent, (CSG_Grid *)m_pObject, Minimum, Maximum);
280
281 if( m_Parameters["COLOR_SYMBOLS"].asInt() == CSG_Map_Symbology::DISCRETE
282 || m_Parameters["COLOR_SYMBOLS"].asInt() == CSG_Map_Symbology::GRADUATED )
283 {
285 }
286
287 //-------------------------------------------------
288 m_Parameters.Set_Parameter("STRETCH_RANGE.MIN", Minimum < Maximum ? Minimum : Maximum);
289 m_Parameters.Set_Parameter("STRETCH_RANGE.MAX", Minimum < Maximum ? Maximum : Minimum);
290
291 const CSG_String Band[3] = { "R", "G", "B" };
292
293 for(int i=0; i<3; i++)
294 {
295 if( m_Parameters["COMPOSITE_" + Band[i]].is_Enabled() && _Get_Stretch_Extent(Extent, m_Parameters["COMPOSITE_" + Band[i]].asGrid(), Minimum, Maximum) )
296 {
297 m_Composite[i].Scaler.Set_Range(Minimum, Maximum);
298 }
299 }
300
301 m_Parameters["STRETCH"].Set_Value(3); // 'manual'
302
303 return( true );
304 }
305
306 return( false );
307}
308
309//---------------------------------------------------------
310bool CSG_Map_Grid::_Get_Stretch_Extent(const CSG_Rect &Extent, CSG_Grid *pGrid, double &Minimum, double &Maximum) const
311{
312 if( pGrid )
313 {
314 switch( m_Stretch_Extent )
315 {
316 default:
317 {
319
320 if( pGrid->Get_Statistics(Extent, s) )
321 {
322 Minimum = s.Get_Minimum() + s.Get_Range() * m_Parameters("STRETCH_LINEAR.MIN")->asDouble() / 100.;
323 Maximum = s.Get_Minimum() + s.Get_Range() * m_Parameters("STRETCH_LINEAR.MAX")->asDouble() / 100.;
324
325 return( true );
326 }
327 }
328 break;
329
330 case 1:
331 {
332 CSG_Simple_Statistics s;
333
334 if( pGrid->Get_Statistics(Extent, s) )
335 {
336 double d = m_Parameters("STRETCH_STDDEV")->asDouble() * s.Get_StdDev();
337
338 Minimum = s.Get_Mean() - d; if( m_Parameters("STRETCH_STDDEV_RANGE")->asBool() && Minimum < s.Get_Minimum() ) { Minimum = s.Get_Minimum(); }
339 Maximum = s.Get_Mean() + d; if( m_Parameters("STRETCH_STDDEV_RANGE")->asBool() && Maximum > s.Get_Maximum() ) { Maximum = s.Get_Maximum(); }
340
341 return( true );
342 }
343 }
344 break;
345
346 case 2:
347 {
348 CSG_Histogram h;
349
350 if( pGrid->Get_Histogram (Extent, h) )
351 {
352 Minimum = h.Get_Quantile(m_Parameters("STRETCH_PERCENT.MIN")->asDouble() / 100.);
353 Maximum = h.Get_Quantile(m_Parameters("STRETCH_PERCENT.MAX")->asDouble() / 100.);
354
355 return( true );
356 }
357 }
358 break;
359 }
360 }
361
362 Minimum = Maximum = 0.;
363
364 return( false );
365}
366
367
369// //
371
372//---------------------------------------------------------
374{
375 if( pChanged )
376 {
377 if( pChanged == m_pObject )
378 {
379 return( true );
380 }
381
382 if( pChanged->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grid )
383 {
384 return( (m_Parameters["COMPOSITE_R"].is_Enabled() && pChanged->asGrid() == m_Parameters["COMPOSITE_R"].asGrid())
385 || (m_Parameters["COMPOSITE_G"].is_Enabled() && pChanged->asGrid() == m_Parameters["COMPOSITE_G"].asGrid())
386 || (m_Parameters["COMPOSITE_B"].is_Enabled() && pChanged->asGrid() == m_Parameters["COMPOSITE_B"].asGrid())
387 );
388 }
389
390 if( pChanged->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grids )
391 {
392 return( (m_Parameters["COMPOSITE_R"].is_Enabled() && m_Parameters["COMPOSITE_R"].asGrid() && pChanged->asGrids() == m_Parameters["COMPOSITE_R"].asGrid()->Get_Owner())
393 || (m_Parameters["COMPOSITE_G"].is_Enabled() && m_Parameters["COMPOSITE_G"].asGrid() && pChanged->asGrids() == m_Parameters["COMPOSITE_G"].asGrid()->Get_Owner())
394 || (m_Parameters["COMPOSITE_B"].is_Enabled() && m_Parameters["COMPOSITE_B"].asGrid() && pChanged->asGrids() == m_Parameters["COMPOSITE_B"].asGrid()->Get_Owner())
395 );
396 }
397 }
398
399 return( false );
400}
401
402//---------------------------------------------------------
404{
405 switch( Band )
406 {
407 case 0: return( Band == m_Parameters["COMPOSITE_THIS"].asInt() ? m_pObject->asGrid() : m_Parameters["COMPOSITE_R"].asGrid() );
408 case 1: return( Band == m_Parameters["COMPOSITE_THIS"].asInt() ? m_pObject->asGrid() : m_Parameters["COMPOSITE_G"].asGrid() );
409 case 2: return( Band == m_Parameters["COMPOSITE_THIS"].asInt() ? m_pObject->asGrid() : m_Parameters["COMPOSITE_B"].asGrid() );
410 }
411
412 return( NULL );
413}
414
415//---------------------------------------------------------
416void CSG_Map_Grid::_Composite_Update(void)
417{
418 const CSG_String Band[3] = { "R", "G", "B" }; // update color composite bands (rgb)
419
420 for(int i=0; i<3; i++) // update bands
421 {
422 CSG_Grid *pGrid = m_Parameters["COMPOSITE_" + Band[i]].asGrid();
423
424 if( !SG_Get_Data_Manager().Exists(pGrid) )
425 {
426 m_Composite[i].pGrid = NULL;
427 }
428 else if( m_Composite[i].pGrid != pGrid )
429 {
430 m_Composite[i].pGrid = pGrid;
431
432 switch( m_Parameters("STRETCH")->asInt() ) // initialize stretch range
433 {
434 case 0: m_Composite[i].Scaler.Set_Linear (pGrid, 0., m_Parameters["STRETCH_LINEAR.MIN"].asDouble(), m_Parameters["STRETCH_LINEAR.MAX"].asDouble()); break;
435 case 1: m_Composite[i].Scaler.Set_StdDev (pGrid, 0., m_Parameters["STRETCH_STDDEV" ].asDouble(), m_Parameters["STRETCH_STDDEV_RANGE" ].asBool ()); break;
436 default: m_Composite[i].Scaler.Set_Percentile(pGrid, 0., m_Parameters["STRETCH_PERCENT.MIN" ].asDouble(), m_Parameters["STRETCH_PERCENT.MAX" ].asDouble()); break;
437 }
438 }
439 }
440}
441
442//---------------------------------------------------------
443void CSG_Map_Grid::_Composite_Get(CComposite Composite[3])
444{
445 if( m_pObject )
446 {
447 switch( m_Parameters("COMPOSITE_THIS")->asInt() )
448 {
449 default: Composite[0].pGrid = m_pObject->asGrid(); Composite[1] = m_Composite[1]; Composite[2] = m_Composite[2]; break; // this = red
450 case 1: Composite[1].pGrid = m_pObject->asGrid(); Composite[0] = m_Composite[0]; Composite[2] = m_Composite[2]; break; // this = green
451 case 2: Composite[2].pGrid = m_pObject->asGrid(); Composite[0] = m_Composite[0]; Composite[1] = m_Composite[1]; break; // this = blue
452 }
453
454 int Mode = m_pSymbology->Get_Stretch_Mode ();
455 double LogScale = m_pSymbology->Get_Stretch_LogScale();
456
457 for(int i=0; i<3; i++)
458 {
459 Composite[i].pReference = m_pObject->asGrid();
460
461 if( Composite[i].pGrid )
462 {
463 switch( m_Parameters("STRETCH")->asInt() )
464 {
465 case 0: Composite[i].Scaler.Set_Linear (Composite[i].pGrid, m_Parameters["STRETCH_LINEAR.MIN"].asDouble(), m_Parameters["STRETCH_LINEAR.MAX"].asDouble(), Mode, LogScale); break;
466 case 1: Composite[i].Scaler.Set_StdDev (Composite[i].pGrid, m_Parameters["STRETCH_STDDEV" ].asDouble(), m_Parameters["STRETCH_STDDEV_RANGE" ].asBool (), Mode, LogScale); break;
467 case 2: Composite[i].Scaler.Set_Percentile(Composite[i].pGrid, m_Parameters["STRETCH_PERCENT.MIN" ].asDouble(), m_Parameters["STRETCH_PERCENT.MAX" ].asDouble(), Mode, LogScale); break;
468 default:
469 if( Composite[i].pGrid == m_pObject->asGrid() )
470 {
471 Composite[i].Scaler.Create(
472 m_Parameters["STRETCH_RANGE.MIN"].asDouble(),
473 m_Parameters["STRETCH_RANGE.MAX"].asDouble(), Mode, LogScale
474 );
475 }
476 break;
477 }
478 }
479 }
480 }
481}
482
483
485// //
487
488//---------------------------------------------------------
489void CSG_Map_Grid::On_Draw(CSG_Map_DC &dc_Map, int Flags)
490{
491 if( m_pObject == NULL || Get_Extent().Intersects(dc_Map.rWorld()) == INTERSECTION_None )
492 {
493 return;
494 }
495
496 //-----------------------------------------------------
497 m_Alpha.Create(m_Parameters("TRANSPARENCY_GRID")->asGrid(),
498 m_Parameters("TRANSPARENCY_GRID_STRETCH.MIN")->asDouble(),
499 m_Parameters("TRANSPARENCY_GRID_STRETCH.MAX")->asDouble()
500 );
501
502 CSG_Map_DC::Mode Mode = m_Parameters("TRANSPARENCY_MODE")->asInt() == 1 ? CSG_Map_DC::Mode::Shade : (
503 (m_pSymbology->Get_Mode() != CSG_Map_Symbology::RGB && m_Alpha.is_Okay()) ||
504 (m_pSymbology->Get_Mode() == CSG_Map_Symbology::RGB && m_Parameters("RGB_ALPHA")->asBool())
506 );
507
508 if( !dc_Map.Draw_Image_Begin(m_Parameters("TRANSPARENCY")->asDouble() / 100., Mode) )
509 {
510 return;
511 }
512
513 //-----------------------------------------------------
514 CSG_Grid_Resampling Resampling = m_Parameters(m_pSymbology->Get_Mode() == CSG_Map_Symbology::CLASSIFIED ? "CLASSIFIED_RESAMPLING" : "STRETCH_RESAMPLING")->asGrid_Resampling();
515
516 //-----------------------------------------------------
517 m_Shading.Create(m_Parameters("SHADING")->asInt(), m_pObject->asGrid(),
518 m_Parameters("SHADING_HEIGHT" )->asDouble(),
519 m_Parameters("SHADING_AZIMUTH")->asDouble(),
520 m_Parameters("SHADING_EXAGG" )->asDouble(),
521 m_Parameters("SHADING_MIN" )->asDouble(),
522 m_Parameters("SHADING_MAX" )->asDouble()
523 );
524
525 //-----------------------------------------------------
526 CComposite Composite[3];
527
528 if( m_Parameters("COLOR_SYMBOLS")->asInt() == CSG_Map_Symbology::COMPOSITE )
529 {
530 _Composite_Get(Composite);
531 }
532
533 //-----------------------------------------------------
534 if( dc_Map.DC2World() >= m_pObject->asGrid()->Get_Cellsize() || Resampling != CSG_Grid_Resampling::NearestNeighbour )
535 {
536 _Draw_Points(dc_Map, Composite, Resampling);
537 }
538 else
539 {
540 _Draw_Cells (dc_Map, Composite);
541 }
542
543 //-----------------------------------------------------
544 dc_Map.Draw_Image_End();
545
546 if( (Flags & LAYER_DRAW_FLAG_NOLABELS) == 0 )
547 {
548 _Draw_Values(dc_Map);
549 }
550
551 if( (Flags & LAYER_DRAW_FLAG_NOEDITS) == 0 )
552 {
553 // _Draw_Edit(dc_Map);
554 }
555}
556
557//---------------------------------------------------------
558void CSG_Map_Grid::_Draw_Cells(CSG_Map_DC &dc_Map, CComposite Composite[3])
559{
560 CSG_Grid *pGrid = m_pObject->asGrid();
561
562 int xa = pGrid->Get_System().Get_xWorld_to_Grid(dc_Map.rWorld().Get_XMin()); if( xa < 0 ) { xa = 0; }
563 int ya = pGrid->Get_System().Get_yWorld_to_Grid(dc_Map.rWorld().Get_YMin()); if( ya < 0 ) { ya = 0; }
564 int xb = pGrid->Get_System().Get_xWorld_to_Grid(dc_Map.rWorld().Get_XMax()); if( xb >= pGrid->Get_NX() ) { xb = pGrid->Get_NX() - 1; }
565 int yb = pGrid->Get_System().Get_yWorld_to_Grid(dc_Map.rWorld().Get_YMax()); if( yb >= pGrid->Get_NY() ) { yb = pGrid->Get_NY() - 1; }
566
567 double dDC = pGrid->Get_Cellsize() * dc_Map.World2DC();
568
569 double axDC = dc_Map.xWorld2DC(pGrid->Get_System().Get_xGrid_to_World(xa)) + dDC / 2.;
570 double ayDC = dc_Map.yWorld2DC(pGrid->Get_System().Get_yGrid_to_World(ya)) - dDC / 2.;
571
572 //-----------------------------------------------------
573 double yDC = ayDC;
574
575 for(int y=ya, yaDC=(int)(ayDC), ybDC=(int)(ayDC+dDC); y<=yb; y++, ybDC=yaDC, yaDC=(int)(yDC-=dDC))
576 {
577 double xDC = axDC;
578
579 for(int x=xa, xaDC=(int)(axDC-dDC), xbDC=(int)(axDC); x<=xb; x++, xaDC=xbDC, xbDC=(int)(xDC+=dDC))
580 {
581 int Color;
582
583 if( m_pSymbology->Get_Mode() != CSG_Map_Symbology::COMPOSITE )
584 {
585 if( pGrid->is_InGrid(x, y) && m_pSymbology->Get_Class_Color_byValue(pGrid->asDouble(x, y), Color) )
586 {
587 dc_Map.Draw_Image_Pixels(xaDC, yaDC, xbDC, ybDC, _Adjust_Color(x, y, Color));
588 }
589 }
590 else
591 {
592 if( Composite[0].Set_Color(((BYTE *)&Color)[0], x, y)
593 && Composite[1].Set_Color(((BYTE *)&Color)[1], x, y)
594 && Composite[2].Set_Color(((BYTE *)&Color)[2], x, y) )
595 {
596 dc_Map.Draw_Image_Pixels(xaDC, yaDC, xbDC, ybDC, _Adjust_Color(x, y, Color));
597 }
598 }
599 }
600 }
601}
602
603//---------------------------------------------------------
604void CSG_Map_Grid::_Draw_Points(CSG_Map_DC &dc_Map, CComposite Composite[3], CSG_Grid_Resampling Resampling)
605{
606 CSG_Grid *pGrid = m_pObject->asGrid();
607
608 CSG_Rect rMap(dc_Map.rWorld()); rMap.Intersect(pGrid->Get_Extent(true));
609
610 int axDC = (int)dc_Map.xWorld2DC(rMap.Get_XMin()); if( axDC < 0 ) { axDC = 0; }
611 int bxDC = (int)dc_Map.xWorld2DC(rMap.Get_XMax()); if( bxDC >= dc_Map.rDC().GetWidth () ) { bxDC = dc_Map.rDC().GetWidth () - 1; }
612 int ayDC = (int)dc_Map.yWorld2DC(rMap.Get_YMin()); if( ayDC >= dc_Map.rDC().GetHeight() ) { ayDC = dc_Map.rDC().GetHeight() - 1; }
613 int byDC = (int)dc_Map.yWorld2DC(rMap.Get_YMax()); if( byDC < 0 ) { byDC = 0; }
614 int nyDC = abs(ayDC - byDC);
615
616 if( pGrid->is_Cached() )
617 {
618 for(int iyDC=0; iyDC<=nyDC; iyDC++)
619 {
620 _Draw_Points(dc_Map, Composite, Resampling, ayDC - iyDC, axDC, bxDC);
621 }
622 }
623 else
624 {
625 #pragma omp parallel for
626 for(int iyDC=0; iyDC<=nyDC; iyDC++)
627 {
628 _Draw_Points(dc_Map, Composite, Resampling, ayDC - iyDC, axDC, bxDC);
629 }
630 }
631}
632
633//---------------------------------------------------------
634void CSG_Map_Grid::_Draw_Points(CSG_Map_DC &dc_Map, CComposite Composite[3], CSG_Grid_Resampling Resampling, int yDC, int axDC, int bxDC)
635{
636 CSG_Point p(dc_Map.xDC2World(axDC), dc_Map.yDC2World( yDC)); CSG_Grid *pGrid = m_pObject->asGrid();
637
638 for(int xDC=axDC; xDC<=bxDC; p.x+=dc_Map.DC2World(), xDC++)
639 {
640 double Value;
641
642 if( pGrid->Get_Value(p, Value, Resampling, false, m_pSymbology->Get_Mode() == CSG_Map_Symbology::RGB) )
643 {
644 int Color;
645
646 if( m_pSymbology->Get_Mode() != CSG_Map_Symbology::COMPOSITE )
647 {
648 if( m_pSymbology->Get_Class_Color_byValue(Value, Color) )
649 {
650 dc_Map.Draw_Image_Pixel(xDC, yDC, _Adjust_Color(p, Color, Resampling));
651 }
652 }
653 else
654 {
655 if( Composite[0].Set_Color(((BYTE *)&Color)[0], p, Resampling)
656 && Composite[1].Set_Color(((BYTE *)&Color)[1], p, Resampling)
657 && Composite[2].Set_Color(((BYTE *)&Color)[2], p, Resampling) )
658 {
659 dc_Map.Draw_Image_Pixel(xDC, yDC, _Adjust_Color(p, Color, Resampling));
660 }
661 }
662 }
663 }
664}
665
666//---------------------------------------------------------
667inline int CSG_Map_Grid::_Adjust_Color(int x, int y, int Color)
668{
669 if( m_Shading.is_Okay() )
670 {
671 m_Shading.Set_Shading(Color, x, y);
672 }
673
674 if( m_Alpha.is_Okay() )
675 {
676 ((BYTE *)&Color)[3] = m_Alpha.Get_Alpha(m_pObject->asGrid()->Get_System(), x, y);
677 }
678
679 return( Color );
680}
681
682//---------------------------------------------------------
683inline int CSG_Map_Grid::_Adjust_Color(const CSG_Point &Point, int Color, CSG_Grid_Resampling Resampling)
684{
685 if( m_Shading.is_Okay() )
686 {
687 m_Shading.Set_Shading(Color, Point, Resampling);
688 }
689
690 if( m_Alpha.is_Okay() )
691 {
692 m_Alpha.Set_Alpha(Color, Point);
693 }
694
695 return( Color );
696}
697
698//---------------------------------------------------------
699void CSG_Map_Grid::_Draw_Values(CSG_Map_DC &dc_Map)
700{
701 CSG_Grid *pGrid = m_pObject->asGrid();
702
703 if( !m_Parameters("VALUES")->asBool() || pGrid->Get_Cellsize() * dc_Map.World2DC() <= 40 )
704 {
705 return;
706 }
707
708 //-----------------------------------------------------
709 double dDC = pGrid->Get_Cellsize() * dc_Map.World2DC();
710 int Decimals = m_Parameters("VALUES_DECIMALS")->asInt();
711 wxFont Font = SG_Get_wxFont(m_Parameters("VALUES_FONT")); Font.SetPointSize((int)(dDC * m_Parameters("VALUES_SIZE")->asDouble() / 100.));
712 dc_Map.SetFont(Font);
713 dc_Map.Get_DC().SetTextForeground(SG_Get_wxColor(m_Parameters("VALUES_FONT")->asColor()));
714
715 int Effect;
716
717 switch( m_Parameters("VALUES_EFFECT")->asInt() )
718 {
719 default: Effect = SG_DC_TEXTEFFECT_NONE ; break;
720 case 1: Effect = SG_DC_TEXTEFFECT_FRAME ; break;
721 case 2: Effect = SG_DC_TEXTEFFECT_TOP ; break;
722 case 3: Effect = SG_DC_TEXTEFFECT_TOPLEFT ; break;
723 case 4: Effect = SG_DC_TEXTEFFECT_LEFT ; break;
724 case 5: Effect = SG_DC_TEXTEFFECT_BOTTOMLEFT ; break;
725 case 6: Effect = SG_DC_TEXTEFFECT_BOTTOM ; break;
726 case 7: Effect = SG_DC_TEXTEFFECT_BOTTOMRIGHT; break;
727 case 8: Effect = SG_DC_TEXTEFFECT_RIGHT ; break;
728 case 9: Effect = SG_DC_TEXTEFFECT_TOPRIGHT ; break;
729 }
730
731 wxColour Effect_Color = m_Parameters("VALUES_EFFECT_COLOR")->asColor();
732
733 //-------------------------------------------------
734 int ax = pGrid->Get_System().Get_xWorld_to_Grid(dc_Map.rWorld().Get_XMin());
735 int ay = pGrid->Get_System().Get_yWorld_to_Grid(dc_Map.rWorld().Get_YMin());
736 int bx = pGrid->Get_System().Get_xWorld_to_Grid(dc_Map.rWorld().Get_XMax());
737 int by = pGrid->Get_System().Get_yWorld_to_Grid(dc_Map.rWorld().Get_YMax());
738
739 if( ax < 0 ) { ax = 0; } if( bx >= pGrid->Get_NX() ) { bx = pGrid->Get_NX() - 1; }
740 if( ay < 0 ) { ax = 0; } if( by >= pGrid->Get_NY() ) { by = pGrid->Get_NY() - 1; }
741
742 double axDC = dc_Map.xWorld2DC(pGrid->Get_System().Get_xGrid_to_World(ax));
743 double ayDC = dc_Map.yWorld2DC(pGrid->Get_System().Get_yGrid_to_World(ay));
744
745 int ny = by - ay;
746
747 //-------------------------------------------------
748 for(int y=0; y<=ny; y++)
749 {
750 double xDC = axDC, yDC = ayDC - y * dDC; // dc_Map.World2DC();
751
752 for(int x=ax; x<=bx; x++, xDC+=dDC)
753 {
754 if( pGrid->is_InGrid(x, ay + y) )
755 {
756 double Value = pGrid->asDouble(x, ay + y);
757
758 switch( m_pSymbology->Get_Mode() )
759 {
761 dc_Map.DrawText(SG_DC_TEXTALIGN_CENTER, (int)xDC, (int)yDC, wxString::Format(
762 "R%03d G%03d B%03d", SG_GET_R((int)Value), SG_GET_G((int)Value), SG_GET_B((int)Value)
763 ), Effect, Effect_Color);
764 break;
765
766 default:
767 dc_Map.DrawText(SG_DC_TEXTALIGN_CENTER, (int)xDC, (int)yDC, wxString::Format(
768 "%.*f", Decimals, Value
769 ), Effect, Effect_Color);
770 break;
771 }
772 }
773 }
774 }
775}
776
777
779// //
781
782//---------------------------------------------------------
784{
785 wxImage Image;
786
787 if( m_pObject && pImage && Get_Image(Image) )
788 {
789 pImage->Create(m_pObject->asGrid(), SG_DATATYPE_Int);
790
791 #pragma omp parallel for
792 for(int y=0; y<pImage->Get_NY(); y++) for(int x=0; x<pImage->Get_NX(); x++)
793 {
794 if( Image.HasAlpha() && !Image.GetAlpha(x, y) )
795 {
796 pImage->Set_NoData(x, y);
797 }
798 else
799 {
800 pImage->Set_Value(x, y, SG_GET_RGB(Image.GetRed(x, y), Image.GetGreen(x, y), Image.GetBlue(x, y)));
801 }
802 }
803
804 return( true );
805 }
806
807 return( false );
808}
809
810//---------------------------------------------------------
811bool CSG_Map_Grid::Get_Image(wxImage &Image, bool bFitSize, int Width, int Height)
812{
813 if( m_pObject )
814 {
815 if( bFitSize || Width < 1 ) { Width = m_pObject->asGrid()->Get_NX(); }
816 if( bFitSize || Height < 1 ) { Height = m_pObject->asGrid()->Get_NY(); }
817
818 if( Width > 0 && Height > 0 && Image.Create(Width, Height) )
819 {
821
822 CSG_Map_DC dc_Map(Get_Extent(), wxRect(0, 0, Width, Height), 1., -1, true);
823
824 On_Draw(dc_Map, false);
825
826 dc_Map.Get_Image(Image);
827
829
830 return( true );
831 }
832 }
833
834 return( false );
835}
836
837//---------------------------------------------------------
838bool CSG_Map_Grid::Get_Bitmap(wxBitmap &Bitmap, bool bFitSize, int Width, int Height)
839{
840 if( m_pObject )
841 {
842 if( bFitSize || Width < 1 ) { Width = bFitSize ? m_pObject->asGrid()->Get_NX() : Bitmap.GetWidth (); }
843 if( bFitSize || Height < 1 ) { Height = bFitSize ? m_pObject->asGrid()->Get_NY() : Bitmap.GetHeight(); }
844
845 if( Width > 0 && Height > 0 && Bitmap.Create(Width, Height) )
846 {
848
849 CSG_Map_DC dc_Map(Get_Extent(), Bitmap.GetSize(), 1., -1, true);
850
851 On_Draw(dc_Map, false);
852
853 dc_Map.Get_Bitmap(Bitmap);
854
856
857 return( true );
858 }
859 }
860
861 return( false );
862}
863
864//---------------------------------------------------------
865bool CSG_Map_Grid::Get_Bitmap_Legend(wxBitmap &Bitmap, double Zoom)
866{
867 if( Zoom > 0. )
868 {
869 wxMemoryDC dc; wxSize s(Get_Legend()->Get_Size(Zoom, 1.));
870
871 Bitmap.Create(s.GetWidth(), s.GetHeight());
872
873 dc.SelectObject(Bitmap);
874 dc.SetBackground(*wxWHITE_BRUSH);
875 dc.Clear();
876
877 Get_Legend()->Draw(dc, Zoom, 1., wxPoint(0, 0));
878
879 dc.SelectObject(wxNullBitmap);
880
881 return( true );
882 }
883
884 return( false );
885}
886
887
889// //
890// //
891// //
893
894//---------------------------------------------------------
bool SG_UI_Process_Set_Busy(bool bOn, const CSG_String &Message)
#define SG_GET_B(rgb)
Definition api_core.h:1350
#define SG_GET_G(rgb)
Definition api_core.h:1349
#define SG_GET_R(rgb)
Definition api_core.h:1348
@ SG_DATATYPE_Int
Definition api_core.h:1050
#define SG_GET_RGB(r, g, b)
Definition api_core.h:1345
#define _TL(s)
Definition api_core.h:1619
class CSG_Grids * asGrids(bool bPolymorph=false) const
virtual TSG_Data_Object_Type Get_ObjectType(void) const =0
Returns the object type as defined by TSG_Data_Object_Type. Used for run time type checking.
class CSG_Grid * asGrid(bool bPolymorph=false) const
int Get_xWorld_to_Grid(double xWorld) const
Definition grid.h:318
int Get_yWorld_to_Grid(double yWorld) const
Definition grid.h:319
double Get_yGrid_to_World(int yGrid) const
Definition grid.h:304
double Get_xGrid_to_World(int xGrid) const
Definition grid.h:303
int Get_NY(void) const
Definition grid.h:564
double Get_Max(void)
Definition grid.cpp:1027
const CSG_Simple_Statistics & Get_Statistics(void)
Definition grid.cpp:1099
bool is_Cached(void) const
Definition grid.h:633
virtual void Set_NoData(int x, int y)
Definition grid.h:730
const CSG_Histogram & Get_Histogram(size_t nClasses=0)
Definition grid.cpp:1175
double Get_Cellsize(void) const
Definition grid.h:567
virtual double asDouble(sLong i, bool bScaled=true) const
Definition grid.h:789
double Get_Min(void)
Definition grid.cpp:1022
virtual void Set_Value(sLong i, BYTE Value, bool bScaled=true)
Definition grid.h:846
bool Create(const CSG_Grid &Grid)
Definition grid.cpp:235
const CSG_Grid_System & Get_System(void) const
Definition grid.h:559
double Get_Value(double x, double y, CSG_Grid_Resampling Resampling=CSG_Grid_Resampling::Bicubic_2, bool bByteWise=false) const
Definition grid.cpp:539
virtual const CSG_Rect & Get_Extent(void)
Definition grid.h:561
int Get_NX(void) const
Definition grid.h:563
bool is_InGrid(int x, int y, bool bCheckNoData=true) const
Definition grid.h:621
double Get_Quantile(double Quantile) const
bool Get_Image(wxImage &Image)
Definition map_dc.cpp:208
double yDC2World(double y)
Definition map_dc.h:161
bool Draw_Image_Begin(double Transparency, Mode Mode=Mode::Transparent)
Definition map_dc.cpp:374
double yWorld2DC(double y, bool bRound=true)
Definition map_dc.h:147
double xDC2World(double x)
Definition map_dc.h:156
const CSG_Rect & rWorld(void) const
Definition map_dc.h:124
double xWorld2DC(double x, bool bRound=true)
Definition map_dc.h:140
wxMemoryDC & Get_DC(void)
Definition map_dc.h:96
const wxRect & rDC(void) const
Definition map_dc.h:129
void Draw_Image_Pixels(int x1, int y1, int x2, int y2, int Color)
Definition map_dc.cpp:433
void Draw_Image_Pixel(int x, int y, int Color)
Definition map_dc.h:186
wxBitmap Get_Bitmap(void)
Definition map_dc.cpp:171
bool Draw_Image_End(void)
Definition map_dc.cpp:418
const double & DC2World(void) const
Definition map_dc.h:154
const double & World2DC(void) const
Definition map_dc.h:131
void SetFont(const wxFont &Font)
Definition map_dc.cpp:471
void DrawText(int Align, int x, int y, const wxString &Text)
Definition map_dc.cpp:616
virtual bool Get_Image(wxImage &Image, bool bFitSize=true, int Width=0, int Height=0)
Definition map_grid.cpp:811
virtual bool Set_Stretch_Extent(const CSG_Rect &Extent)
Definition map_grid.cpp:267
virtual bool Add_Parameters(CSG_Parameters &Parameters)
Definition map_grid.cpp:81
virtual bool Get_Bitmap(wxBitmap &Bitmap, bool bFitSize=true, int Width=0, int Height=0)
Definition map_grid.cpp:838
virtual bool Parameters_Changed(void)
Definition map_grid.cpp:250
CSG_Grid * Get_Composite_Band(int Band)
Definition map_grid.cpp:403
virtual bool Parameter_Changed(CSG_Parameters &Parameters, CSG_Parameter &Parameter, int Flags)
Definition map_grid.cpp:159
virtual bool Update(CSG_Data_Object *pChanged)
Definition map_grid.cpp:373
virtual bool DataObject_Changed(void)
Definition map_grid.cpp:236
virtual bool asImage(CSG_Grid *pImage)
Definition map_grid.cpp:783
virtual void On_Draw(CSG_Map_DC &dc_Map, int Flags)
Definition map_grid.cpp:489
virtual bool Get_Bitmap_Legend(wxBitmap &Bitmap, double Zoom)
Definition map_grid.cpp:865
CSG_Map_Grid(CSG_Grid *pGrid=NULL)
Definition map_grid.cpp:67
class CSG_Map_Legend * Get_Legend(void)
Definition map_layer.h:137
virtual bool Parameters_Changed(void)
virtual bool DataObject_Changed(void)
virtual bool Parameter_Changed(CSG_Parameters &Parameters, CSG_Parameter &Parameter, int Flags)
CSG_Data_Object * m_pObject
Definition map_layer.h:151
bool Set_Stretch_Range(double Minimum, double Maximum)
bool Set_Object(CSG_Data_Object *pObject)
CSG_Rect Get_Extent(void) const
CSG_Parameters m_Parameters
Definition map_layer.h:149
class CSG_Map_Symbology * m_pSymbology
Definition map_layer.h:153
virtual bool Add_Parameters(CSG_Parameters &Parameters)
CSG_Map_Layer(void)
Definition map_layer.h:90
void Draw(wxDC &dc, double Zoom, double Zoom_Map, wxPoint Position, wxSize *pSize=NULL)
bool Set_Collapsed(bool bOn=true)
bool Set_Children_Enabled(bool bEnabled=true)
bool asBool(void) const
Definition parameters.h:286
CSG_Grid * asGrid(void) const
bool Cmp_Identifier(const CSG_String &Identifier) const
int asInt(void) const
Definition parameters.h:287
CSG_Parameter * Add_Grid_Resampling(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, CSG_Grid_Resampling Methods=CSG_Grid_Resampling::Interpolations, CSG_Grid_Resampling Default=CSG_Grid_Resampling::Bicubic_2)
CSG_Parameter * Add_Choice(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, const CSG_String &Items, int Default=0)
void Set_Enabled(bool bEnabled=true)
CSG_Parameter * Add_Double(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, double Value=0.0, double Minimum=0.0, bool bMinimum=false, double Maximum=0.0, bool bMaximum=false)
bool Create(const CSG_Parameters &Parameters)
CSG_Parameter * Add_Int(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Value=0, int Minimum=0, bool bMinimum=false, int Maximum=0, bool bMaximum=false)
CSG_Parameter * Add_Node(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, bool bCollapsed=false)
CSG_Parameter * Add_Color(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Value=0)
bool Set_Parameter(const CSG_String &ID, CSG_Parameter *pValue)
CSG_Parameter * Add_Font(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, const SG_Char *pInit=NULL)
CSG_Parameter * Add_Bool(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, bool Value=false)
CSG_Parameter * Add_Grid(const CSG_String &ParentID, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint, bool bSystem_Dependent=true, TSG_Data_Type Preferred_Type=SG_DATATYPE_Undefined)
double Get_XMax(void) const
Definition geo_tools.h:506
double Get_XMin(void) const
Definition geo_tools.h:505
double Get_YMin(void) const
Definition geo_tools.h:507
double Get_YMax(void) const
Definition geo_tools.h:508
double Get_Maximum(void)
Definition mat_tools.h:749
double Get_Mean(void)
Definition mat_tools.h:753
double Get_StdDev(void)
Definition mat_tools.h:755
double Get_Minimum(void)
Definition mat_tools.h:748
double Get_Range(void)
Definition mat_tools.h:750
static CSG_String Format(const char *Format,...)
bool Create(const class wxString *pString)
CSG_Data_Manager & SG_Get_Data_Manager(void)
@ SG_DATAOBJECT_TYPE_Grids
Definition dataobject.h:119
@ SG_DATAOBJECT_TYPE_Grid
Definition dataobject.h:118
wxColour SG_Get_wxColor(int Color)
Definition dc_helper.cpp:70
wxFont SG_Get_wxFont(CSG_Parameter *pFont)
#define SG_DC_TEXTEFFECT_TOPRIGHT
Definition dc_helper.h:149
#define SG_DC_TEXTEFFECT_LEFT
Definition dc_helper.h:144
#define SG_DC_TEXTALIGN_CENTER
Definition dc_helper.h:135
#define SG_DC_TEXTEFFECT_BOTTOM
Definition dc_helper.h:146
#define SG_DC_TEXTEFFECT_NONE
Definition dc_helper.h:141
#define SG_DC_TEXTEFFECT_BOTTOMRIGHT
Definition dc_helper.h:147
#define SG_DC_TEXTEFFECT_TOPLEFT
Definition dc_helper.h:143
#define SG_DC_TEXTEFFECT_BOTTOMLEFT
Definition dc_helper.h:145
#define SG_DC_TEXTEFFECT_RIGHT
Definition dc_helper.h:148
#define SG_DC_TEXTEFFECT_TOP
Definition dc_helper.h:142
#define SG_DC_TEXTEFFECT_FRAME
Definition dc_helper.h:150
@ INTERSECTION_None
Definition geo_tools.h:102
CSG_Grid_Resampling
Definition grid.h:156
#define LAYER_DRAW_FLAG_NOLABELS
Definition map_layer.h:78
#define LAYER_DRAW_FLAG_NOEDITS
Definition map_layer.h:77
#define asDouble(i)
#define PARAMETER_CHECK_ENABLE
Definition parameters.h:191
#define PARAMETER_CHECK_VALUES
Definition parameters.h:190
#define PARAMETER_INPUT_OPTIONAL
Definition parameters.h:103