1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                    User Interface                     //
9 //                                                       //
10 //                    Program: SAGA                      //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                 WKSP_Layer_Classify.h                 //
15 //                                                       //
16 //          Copyright (C) 2005 by 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 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Goettingen               //
42 //                Goldschmidtstr. 5                      //
43 //                37077 Goettingen                       //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #ifndef _HEADER_INCLUDED__SAGA_GUI__WKSP_Layer_Classify_H
52 #define _HEADER_INCLUDED__SAGA_GUI__WKSP_Layer_Classify_H
53 
54 
55 ///////////////////////////////////////////////////////////
56 //														 //
57 //														 //
58 //														 //
59 ///////////////////////////////////////////////////////////
60 
61 //---------------------------------------------------------
62 #include <wx/string.h>
63 
64 #include <saga_api/saga_api.h>
65 
66 
67 ///////////////////////////////////////////////////////////
68 //														 //
69 //														 //
70 //														 //
71 ///////////////////////////////////////////////////////////
72 
73 //---------------------------------------------------------
74 enum
75 {
76 	CLASSIFY_SINGLE	= 0,
77 	CLASSIFY_LUT,
78 	CLASSIFY_DISCRETE,
79 	CLASSIFY_GRADUATED,
80 	CLASSIFY_OVERLAY,
81 	CLASSIFY_RGB,
82 	CLASSIFY_SHADE
83 };
84 
85 //---------------------------------------------------------
86 enum
87 {
88 	LUT_COLOR		= 0,
89 	LUT_TITLE,
90 	LUT_DESCRIPTION,
91 	LUT_MIN,
92 	LUT_MAX
93 };
94 
95 //---------------------------------------------------------
96 enum
97 {
98 	METRIC_MODE_NORMAL	= 0,
99 	METRIC_MODE_LOGUP,
100 	METRIC_MODE_LOGDOWN
101 };
102 
103 //---------------------------------------------------------
104 enum
105 {
106 	SHADE_MODE_DSC_GREY	= 0,
107 	SHADE_MODE_ASC_GREY,
108 	SHADE_MODE_DSC_CYAN,
109 	SHADE_MODE_ASC_CYAN,
110 	SHADE_MODE_DSC_MAGENTA,
111 	SHADE_MODE_ASC_MAGENTA,
112 	SHADE_MODE_DSC_YELLOW,
113 	SHADE_MODE_ASC_YELLOW
114 };
115 
116 
117 ///////////////////////////////////////////////////////////
118 //														 //
119 //														 //
120 //														 //
121 ///////////////////////////////////////////////////////////
122 
123 //---------------------------------------------------------
124 class CSG_Scaler
125 {
126 public:
127 	typedef enum EInterval
128 	{
129 		LINEAR = 0, INCREASING, DECREASING
130 	}
131 	TInterval;
132 
133 	//-----------------------------------------------------
134 	CSG_Scaler(void);
135 
136 								CSG_Scaler			(double Minimum, double Maximum, double Interval = 0.);
137 	bool						Create				(double Minimum, double Maximum, double Interval = 0.);
138 
139 	//-----------------------------------------------------
140 	bool						Set_Linear			(CSG_Table *pTable, int Field, double Interval, double Minimum, double Maximum);
141 	bool						Set_StdDev			(CSG_Table *pTable, int Field, double Interval, double StdDev, bool bKeepInRange);
142 	bool						Set_Percentile		(CSG_Table *pTable, int Field, double Interval, double Minimum, double Maximum);
143 
144 	bool						Set_Linear			(CSG_Grid  *pGrid            , double Interval, double Minimum, double Maximum);
145 	bool						Set_StdDev			(CSG_Grid  *pGrid            , double Interval, double StdDev, bool bKeepInRange);
146 	bool						Set_Percentile		(CSG_Grid  *pGrid            , double Interval, double Minimum, double Maximum);
147 
148 	bool						Set_Linear			(CSG_Grids *pGrids           , double Interval, double Minimum, double Maximum);
149 	bool						Set_StdDev			(CSG_Grids *pGrids           , double Interval, double StdDev, bool bKeepInRange);
150 	bool						Set_Percentile		(CSG_Grids *pGrids           , double Interval, double Minimum, double Maximum);
151 
152 	//-----------------------------------------------------
Get_Minimum(void)153 	double						Get_Minimum			(void)	const	{	return( m_Minimum           );	}
Get_Maximum(void)154 	double						Get_Maximum			(void)	const	{	return( m_Minimum + m_Range );	}
Get_Range(void)155 	double						Get_Range			(void)	const	{	return(             m_Range );	}
156 	bool						Set_Range			(double Minimum, double Maximum);
157 
Get_Interval_Mode(void)158 	TInterval					Get_Interval_Mode	(void)	const	{	return( m_Interval          );	}
Get_Interval(void)159 	double						Get_Interval		(void)	const	{	return( m_LogRange          );	}
160 	bool						Set_Interval		(double Interval);
161 
162 	//-----------------------------------------------------
to_Relative(double Value)163 	double						to_Relative			(double Value)	const
164 	{
165 		if( m_Range > 0. )
166 		{
167 			Value	= (Value - m_Minimum) / m_Range;
168 
169 			switch( m_Interval )
170 			{
171 			default:
172 				return( Value );
173 
174 			case INCREASING:
175 				return( Value <= 0. ? 0. :      (log(1. + m_LogRange * (     Value)) / log(1. + m_LogRange)) );
176 
177 			case DECREASING:
178 				return( Value >= 1. ? 1. : 1. - (log(1. + m_LogRange * (1. - Value)) / log(1. + m_LogRange)) );
179 			}
180 		}
181 
182 		return( 0. );
183 	}
184 
185 	//-----------------------------------------------------
from_Relative(double Value)186 	double						from_Relative		(double Value)	const
187 	{
188 		if( m_Range > 0. )
189 		{
190 			switch( m_Interval )
191 			{
192 			default:
193 				break;
194 
195 			case INCREASING:
196 				Value	=      ((exp(log(1. + m_LogRange) * (     Value)) - 1.) / m_LogRange);
197 				break;
198 
199 			case DECREASING:
200 				Value	= 1. - ((exp(log(1. + m_LogRange) * (1. - Value)) - 1.) / m_LogRange);
201 				break;
202 			}
203 
204 			return( m_Minimum + (m_Range * Value) );
205 		}
206 
207 		return( m_Minimum );
208 	}
209 
210 
211 protected:
212 
213 	TInterval		m_Interval;
214 
215 	double			m_Minimum, m_Range, m_LogRange;
216 
217 };
218 
219 
220 ///////////////////////////////////////////////////////////
221 //														 //
222 //														 //
223 //														 //
224 ///////////////////////////////////////////////////////////
225 
226 //---------------------------------------------------------
227 class CWKSP_Layer_Classify
228 {
229 public: ///////////////////////////////////////////////////
230 	CWKSP_Layer_Classify(void);
231 	virtual ~CWKSP_Layer_Classify(void);
232 
233 	bool						Initialise				(class CWKSP_Layer *pLayer, CSG_Table *pLUT, CSG_Colors *pColors);
234 
Set_Mode(int Mode)235 	void						Set_Mode				(int Mode)	{	m_Mode			= Mode;	}
Get_Mode(void)236 	int							Get_Mode				(void)		{	return( m_Mode );		}
237 
Set_Shade_Mode(int Mode)238 	void						Set_Shade_Mode			(int Mode)	{	m_Shade_Mode	= Mode;	}
Get_Shade_Mode(void)239 	int							Get_Shade_Mode			(void)		{	return( m_Shade_Mode );	}
240 
241 	void						Set_Unique_Color		(int Color);
Get_Unique_Color(void)242 	int							Get_Unique_Color		(void)		{	return( m_UNI_Color );	}
243 
244 
245 	///////////////////////////////////////////////////////
246 
247 	//-----------------------------------------------------
248 	bool						Set_Class_Count			(int Count);
249 
Get_Class_Count(void)250 	int							Get_Class_Count			(void)
251 	{
252 		switch( m_Mode )
253 		{
254 		case CLASSIFY_SINGLE   : default:
255 			return( 1 );
256 
257 		case CLASSIFY_LUT      :
258 			return( m_pLUT->Get_Record_Count() );
259 
260 		case CLASSIFY_GRADUATED:
261 		case CLASSIFY_SHADE    :
262 		case CLASSIFY_OVERLAY  :
263 			return( m_Count );
264 
265 		case CLASSIFY_DISCRETE   :
266 			return( m_pColors->Get_Count() );
267 		}
268 	}
269 
270 	//-----------------------------------------------------
Get_Class(double Value)271 	int							Get_Class				(double Value)
272 	{
273 		switch( m_Mode )
274 		{
275 		case CLASSIFY_SINGLE   : default:
276 			return( 0 );
277 
278 		case CLASSIFY_LUT      :
279 			return( _LUT_Get_Class(Value) );
280 
281 		case CLASSIFY_GRADUATED:
282 		case CLASSIFY_DISCRETE   :
283 		case CLASSIFY_SHADE    :
284 		case CLASSIFY_OVERLAY  :
285 			return( _METRIC_Get_Class(Value) );
286 		}
287 	}
288 
Get_Class(const CSG_String & Value)289 	int							Get_Class				(const CSG_String &Value)
290 	{
291 		if( m_Mode == CLASSIFY_LUT )
292 		{
293 			return( _LUT_Get_Class(Value) );
294 		}
295 
296 		return( Get_Class(Value.asDouble()) );
297 	}
298 
299 	//-----------------------------------------------------
300 	double						Get_Class_Value_Minimum	(int iClass);
301 	double						Get_Class_Value_Center	(int iClass);
302 	double						Get_Class_Value_Maximum	(int iClass);
303 	wxString					Get_Class_Name			(int iClass);
304 	wxString					Get_Class_Name_byValue	(double          Value);
305 	wxString					Get_Class_Name_byValue	(const wxString &Value);
306 
307 
308 	///////////////////////////////////////////////////////
309 
310 	//-----------------------------------------------------
Get_Class_Color(int iClass,int & Color)311 	bool						Get_Class_Color			(int iClass, int &Color)
312 	{
313 		switch( m_Mode )
314 		{
315 		case CLASSIFY_SINGLE   : default:
316 			Color	= m_UNI_Color;
317 			break;
318 
319 		case CLASSIFY_LUT      :
320 			if( iClass < 0 || iClass >= m_pLUT->Get_Record_Count() )
321 			{
322 				Color	= m_UNI_Color;
323 
324 				return( false );
325 			}
326 
327 			Color	= m_pLUT->Get_Record(iClass)->asInt(LUT_COLOR);
328 			break;
329 
330 
331 		case CLASSIFY_DISCRETE   :
332 			Color	= m_pColors->Get_Color(iClass < 0 ? 0 : iClass >= m_pColors->Get_Count() ? m_pColors->Get_Count() - 1 : iClass);
333 			break;
334 
335 		case CLASSIFY_GRADUATED:
336 		case CLASSIFY_SHADE    :
337 		case CLASSIFY_OVERLAY  :
338 			Get_Class_Color_byValue(Get_RelativeToMetric(iClass / (double)m_Count), Color);
339 			break;
340 		}
341 
342 		return( true );
343 	}
344 
345 	//-----------------------------------------------------
Get_Class_Color(int iClass)346 	int							Get_Class_Color			(int iClass)
347 	{
348 		int		Color;
349 
350 		return( Get_Class_Color(iClass, Color) ? Color : 0 );
351 	}
352 
353 	//-----------------------------------------------------
Get_Class_Color_byValue(double Value,int & Color)354 	bool						Get_Class_Color_byValue	(double Value, int &Color)
355 	{
356 		switch( m_Mode )
357 		{
358 		case CLASSIFY_SINGLE   : default:
359 			{
360 				return( Get_Class_Color(0, Color) );
361 			}
362 
363 		case CLASSIFY_LUT      :
364 			{
365 				return( Get_Class_Color(_LUT_Get_Class(Value), Color) );
366 			}
367 
368 		case CLASSIFY_DISCRETE   :
369 			{
370 				return( Get_Class_Color(_METRIC_Get_Class(Value), Color) );
371 			}
372 
373 		case CLASSIFY_GRADUATED:
374 			{
375 				double	iClass	= Get_MetricToRelative(Value) * (m_pColors->Get_Count() - 1);
376 
377 				if( iClass < 0 )
378 				{
379 					Color	= m_pColors->Get_Color(0);
380 				}
381 				else if( iClass >= m_pColors->Get_Count() - 1 )
382 				{
383 					Color	= m_pColors->Get_Color(m_pColors->Get_Count() - 1);
384 				}
385 				else
386 				{
387 					int		a	= m_pColors->Get_Color(    (int)iClass);
388 					int		b	= m_pColors->Get_Color(1 + (int)iClass);
389 					double	d	= iClass - (int)iClass;
390 
391 					Color	= SG_GET_RGB(
392 						SG_GET_R(a) + d * (SG_GET_R(b) - SG_GET_R(a)),
393 						SG_GET_G(a) + d * (SG_GET_G(b) - SG_GET_G(a)),
394 						SG_GET_B(a) + d * (SG_GET_B(b) - SG_GET_B(a))
395 					);
396 				}
397 
398 				return( true );
399 			}
400 
401 		case CLASSIFY_SHADE    :
402 			{
403 				int	iClass	= (int)(255.0 * Get_MetricToRelative(Value));
404 
405 				if( iClass < 0 ) iClass = 0; else if( iClass > 255 ) iClass = 255;
406 
407 				switch( m_Shade_Mode )
408 				{
409 				default:
410 				case SHADE_MODE_DSC_GREY   : Color = SG_GET_RGB(255 - iClass, 255 - iClass, 255 - iClass);	break;
411 				case SHADE_MODE_DSC_CYAN   : Color = SG_GET_RGB(255 - iClass, 255         , 255         );	break;
412 				case SHADE_MODE_DSC_MAGENTA: Color = SG_GET_RGB(255         , 255 - iClass, 255         );	break;
413 				case SHADE_MODE_DSC_YELLOW : Color = SG_GET_RGB(255         , 255         , 255 - iClass);	break;
414 				case SHADE_MODE_ASC_GREY   : Color = SG_GET_RGB(      iClass,       iClass,       iClass);	break;
415 				case SHADE_MODE_ASC_CYAN   : Color = SG_GET_RGB(      iClass, 255         , 255         );	break;
416 				case SHADE_MODE_ASC_MAGENTA: Color = SG_GET_RGB(255         ,       iClass, 255         );	break;
417 				case SHADE_MODE_ASC_YELLOW : Color = SG_GET_RGB(255         , 255         ,       iClass);	break;
418 				}
419 
420 				return( true );
421 			}
422 
423 		case CLASSIFY_OVERLAY  :
424 			{
425 				int	iClass	= (int)(255.0 * Get_MetricToRelative(Value));
426 
427 				if( iClass < 0 ) iClass = 0; else if( iClass > 255 ) iClass = 255;
428 
429 				Color	= SG_GET_RGB(iClass, iClass, iClass);
430 
431 				return( true );
432 			}
433 
434 		case CLASSIFY_RGB      :
435 			{
436 				Color	= (int)Value;
437 
438 				return( true );
439 			}
440 		}
441 	}
442 
Get_Class_Color_byValue(const CSG_String & Value,int & Color)443 	bool						Get_Class_Color_byValue	(const CSG_String &Value, int &Color)
444 	{
445 		if( m_Mode == CLASSIFY_LUT )
446 		{
447 			return( Get_Class_Color(_LUT_Get_Class(Value), Color) );
448 		}
449 
450 		return( Get_Class_Color(Value.asDouble(), Color) );
451 	}
452 
453 	//-----------------------------------------------------
Get_Class_Color_byValue(double Value)454 	int							Get_Class_Color_byValue	(double Value)
455 	{
456 		int		Color;
457 
458 		return( Get_Class_Color_byValue(Value, Color) ? Color : 0 );
459 	}
460 
Get_Class_Color_byValue(const CSG_String & Value)461 	int							Get_Class_Color_byValue	(const CSG_String &Value)
462 	{
463 		int		Color;
464 
465 		return( Get_Class_Color_byValue(Value, Color) ? Color : 0 );
466 	}
467 
468 
469 	///////////////////////////////////////////////////////
470 
471 	//-----------------------------------------------------
472 	void						Set_Metric				(int Mode, double LogFactor, double zMin, double zMax);
Get_Metric_Mode(void)473 	int							Get_Metric_Mode			(void)		{	return( m_zMode );		}
Get_Metric_Colors(void)474 	CSG_Colors *				Get_Metric_Colors		(void)		{	return( m_pColors );	}
Get_Metric_Minimum(void)475 	double						Get_Metric_Minimum		(void)	const	{	return( m_zMin            );	}
Get_Metric_Maximum(void)476 	double						Get_Metric_Maximum		(void)	const	{	return( m_zMin + m_zRange );	}
Get_Metric_Range(void)477 	double						Get_Metric_Range		(void)	const	{	return(          m_zRange );	}
Get_Metric_LogFactor(void)478 	double						Get_Metric_LogFactor	(void)	const	{	return( m_zLogRange );	}
479 
480 	void						Metric2EqualElements	(void);
481 
482 	//-----------------------------------------------------
Get_MetricToRelative(double Value)483 	double						Get_MetricToRelative	(double Value)
484 	{
485 		if( m_zRange > 0.0 )
486 		{
487 			Value	= (Value - m_zMin) / m_zRange;
488 
489 			switch( m_zMode )
490 			{
491 			default:
492 				return( Value );
493 
494 			case METRIC_MODE_LOGUP:
495 				return( Value > 0.0 ?       (log(1.0 + m_zLogRange * (      Value)) / m_zLogMax) : 0.0 );
496 
497 			case METRIC_MODE_LOGDOWN:
498 				return( Value < 1.0 ? 1.0 - (log(1.0 + m_zLogRange * (1.0 - Value)) / m_zLogMax) : 1.0 );
499 			}
500 		}
501 
502 		return( 0.0 );
503 	}
504 
505 	//-----------------------------------------------------
Get_RelativeToMetric(double Value)506 	double						Get_RelativeToMetric	(double Value)
507 	{
508 		switch( m_zMode )
509 		{
510 		case METRIC_MODE_LOGUP:
511 			Value	=       ((exp(m_zLogMax * (      Value)) - 1.0) / m_zLogRange);
512 			break;
513 
514 		case METRIC_MODE_LOGDOWN:
515 			Value	= 1.0 - ((exp(m_zLogMax * (1.0 - Value)) - 1.0) / m_zLogRange);
516 			break;
517 		}
518 
519 		return( m_zMin + (m_zRange * Value) );
520 	}
521 
522 
523 	///////////////////////////////////////////////////////
524 
525 	//-----------------------------------------------------
526 	bool							Histogram_Update	(void);
527 
Histogram_Get(void)528 	const CSG_Histogram &			Histogram_Get		(void)	const	{	return( m_Histogram );	}
529 
Statistics_Get(void)530 	const CSG_Simple_Statistics &	Statistics_Get		(void)	const	{	return( m_Statistics );	}
531 
532 
533 protected: ////////////////////////////////////////////////
534 
535 	int							m_Mode, m_zMode, m_Shade_Mode, m_Count, m_UNI_Color;
536 
537 	double						m_zMin, m_zRange, m_zLogRange, m_zLogMax;
538 
539 	CSG_Histogram				m_Histogram;
540 
541 	CSG_Simple_Statistics		m_Statistics;
542 
543 	CSG_Colors					*m_pColors;
544 
545 	CSG_Table					*m_pLUT;
546 
547 	class CWKSP_Layer			*m_pLayer;
548 
549 
550 	//-----------------------------------------------------
551 	int							_LUT_Cmp_Class			(double Value, int iClass);
552 	int							_LUT_Get_Class			(double Value);
553 
554 	int							_LUT_Cmp_Class			(const CSG_String &Value, int iClass);
555 	int							_LUT_Get_Class			(const CSG_String &Value);
556 
_METRIC_Get_Class(double Value)557 	int							_METRIC_Get_Class		(double Value)
558 	{
559 		if( Value < m_zMin )
560 		{
561 			return( -1 );
562 		}
563 
564 		if( Value > m_zMin + m_zRange )
565 		{
566 			return( Get_Class_Count() );
567 		}
568 
569 		int	Class	= (int)(Get_MetricToRelative(Value) * Get_Class_Count());
570 
571 		return( Class < 0 ? 0 : Class < Get_Class_Count() ? Class : Get_Class_Count() - 1 );
572 	}
573 
574 
575 	//-----------------------------------------------------
576 	bool						_Histogram_Update		(CSG_Grid  *pGrid );
577 	bool						_Histogram_Update		(CSG_Grids *pGrids);
578 	bool						_Histogram_Update		(CSG_Shapes *pShapes, int Attribute, int Normalize = -1, double Scale = 1.);
579 
580 };
581 
582 
583 ///////////////////////////////////////////////////////////
584 //														 //
585 //														 //
586 //														 //
587 ///////////////////////////////////////////////////////////
588 
589 //---------------------------------------------------------
590 #endif // #ifndef _HEADER_INCLUDED__SAGA_GUI__WKSP_Layer_Classify_H
591