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.cpp //
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 #include "helper.h"
52
53 #include "wksp_layer.h"
54 #include "wksp_layer_classify.h"
55 #include "wksp_grid.h"
56 #include "wksp_grids.h"
57 #include "wksp_shapes.h"
58 #include "wksp_pointcloud.h"
59
60
61 ///////////////////////////////////////////////////////////
62 // //
63 // //
64 // //
65 ///////////////////////////////////////////////////////////
66
67 //---------------------------------------------------------
CSG_Scaler(void)68 CSG_Scaler::CSG_Scaler(void)
69 {
70 Create(0., 0.);
71 }
72
73 //-----------------------------------------------------
CSG_Scaler(double Minimum,double Maximum,double Interval)74 CSG_Scaler::CSG_Scaler(double Minimum, double Maximum, double Interval)
75 {
76 Create(Minimum, Maximum, Interval);
77 }
78
79 //-----------------------------------------------------
Create(double Minimum,double Maximum,double Interval)80 bool CSG_Scaler::Create(double Minimum, double Maximum, double Interval)
81 {
82 return( Set_Interval(Interval) && Set_Range(Minimum, Maximum) );
83 }
84
85 //-----------------------------------------------------
Set_Range(double Minimum,double Maximum)86 bool CSG_Scaler::Set_Range(double Minimum, double Maximum)
87 {
88 m_Minimum = Minimum < Maximum ? Minimum : Maximum;
89 m_Range = Minimum < Maximum ? Maximum - Minimum : Minimum - Maximum;
90
91 return( m_Range > 0. );
92 }
93
Set_Interval(double Interval)94 bool CSG_Scaler::Set_Interval(double Interval)
95 {
96 m_Interval = Interval < 0. ? DECREASING : Interval > 0. ? INCREASING : LINEAR;
97 m_LogRange = fabs(Interval);
98
99 return( true );
100 }
101
102 //-----------------------------------------------------
Set_Linear(CSG_Table * pTable,int Field,double Interval,double Minimum,double Maximum)103 bool CSG_Scaler::Set_Linear(CSG_Table *pTable, int Field, double Interval, double Minimum, double Maximum)
104 {
105 Minimum = pTable->Get_Minimum(Field) + pTable->Get_Range(Field) * Minimum / 100.;
106 Maximum = pTable->Get_Minimum(Field) + pTable->Get_Range(Field) * Maximum / 100.;
107
108 return( Create(Minimum, Maximum, Interval) );
109 }
110
Set_StdDev(CSG_Table * pTable,int Field,double Interval,double StdDev,bool bKeepInRange)111 bool CSG_Scaler::Set_StdDev(CSG_Table *pTable, int Field, double Interval, double StdDev, bool bKeepInRange)
112 {
113 double Minimum = pTable->Get_Mean(Field) - StdDev * pTable->Get_StdDev(Field); if( bKeepInRange && Minimum < pTable->Get_Minimum(Field) ) Minimum = pTable->Get_Minimum(Field);
114 double Maximum = pTable->Get_Mean(Field) + StdDev * pTable->Get_StdDev(Field); if( bKeepInRange && Maximum > pTable->Get_Maximum(Field) ) Maximum = pTable->Get_Maximum(Field);
115
116 return( Create(Minimum, Maximum, Interval) );
117 }
118
Set_Percentile(CSG_Table * pTable,int Field,double Interval,double Minimum,double Maximum)119 bool CSG_Scaler::Set_Percentile(CSG_Table *pTable, int Field, double Interval, double Minimum, double Maximum)
120 {
121 return( false );
122
123 // double Minimum = pTable->Get_Percentile(Field, Percentile);
124 // double Maximum = pTable->Get_Percentile(Field, 100. - Percentile);
125
126 // return( Create(Minimum, Maximum, Interval) );
127 }
128
129
130 //-----------------------------------------------------
Set_Linear(CSG_Grid * pGrid,double Interval,double Minimum,double Maximum)131 bool CSG_Scaler::Set_Linear(CSG_Grid *pGrid, double Interval, double Minimum, double Maximum)
132 {
133 Minimum = pGrid->Get_Min() + pGrid->Get_Range() * Minimum / 100.;
134 Maximum = pGrid->Get_Min() + pGrid->Get_Range() * Maximum / 100.;
135
136 return( Create(Minimum, Maximum, Interval) );
137 }
138
Set_StdDev(CSG_Grid * pGrid,double Interval,double StdDev,bool bKeepInRange)139 bool CSG_Scaler::Set_StdDev(CSG_Grid *pGrid, double Interval, double StdDev, bool bKeepInRange)
140 {
141 double Minimum = pGrid->Get_Mean() - StdDev * pGrid->Get_StdDev(); if( bKeepInRange && Minimum < pGrid->Get_Min() ) Minimum = pGrid->Get_Min();
142 double Maximum = pGrid->Get_Mean() + StdDev * pGrid->Get_StdDev(); if( bKeepInRange && Maximum > pGrid->Get_Max() ) Maximum = pGrid->Get_Max();
143
144 return( Create(Minimum, Maximum, Interval) );
145 }
146
Set_Percentile(CSG_Grid * pGrid,double Interval,double Minimum,double Maximum)147 bool CSG_Scaler::Set_Percentile(CSG_Grid *pGrid, double Interval, double Minimum, double Maximum)
148 {
149 Minimum = pGrid->Get_Percentile(Minimum);
150 Maximum = pGrid->Get_Percentile(Maximum);
151
152 return( Create(Minimum, Maximum, Interval) );
153 }
154
155 //-----------------------------------------------------
Set_Linear(CSG_Grids * pGrids,double Interval,double Minimum,double Maximum)156 bool CSG_Scaler::Set_Linear(CSG_Grids *pGrids, double Interval, double Minimum, double Maximum)
157 {
158 Minimum = pGrids->Get_Min() + pGrids->Get_Range() * Minimum / 100.;
159 Maximum = pGrids->Get_Min() + pGrids->Get_Range() * Maximum / 100.;
160
161 return( Create(Minimum, Maximum, Interval) );
162 }
163
Set_StdDev(CSG_Grids * pGrids,double Interval,double StdDev,bool bKeepInRange)164 bool CSG_Scaler::Set_StdDev(CSG_Grids *pGrids, double Interval, double StdDev, bool bKeepInRange)
165 {
166 double Minimum = pGrids->Get_Mean() - StdDev * pGrids->Get_StdDev(); if( bKeepInRange && Minimum < pGrids->Get_Min() ) Minimum = pGrids->Get_Min();
167 double Maximum = pGrids->Get_Mean() + StdDev * pGrids->Get_StdDev(); if( bKeepInRange && Maximum > pGrids->Get_Max() ) Maximum = pGrids->Get_Max();
168
169 return( Create(Minimum, Maximum, Interval) );
170 }
171
Set_Percentile(CSG_Grids * pGrids,double Interval,double Minimum,double Maximum)172 bool CSG_Scaler::Set_Percentile(CSG_Grids *pGrids, double Interval, double Minimum, double Maximum)
173 {
174 Minimum = pGrids->Get_Percentile(Minimum);
175 Maximum = pGrids->Get_Percentile(Maximum);
176
177 return( Create(Minimum, Maximum, Interval) );
178 }
179
180
181 ///////////////////////////////////////////////////////////
182 // //
183 // //
184 // //
185 ///////////////////////////////////////////////////////////
186
187 //---------------------------------------------------------
CWKSP_Layer_Classify(void)188 CWKSP_Layer_Classify::CWKSP_Layer_Classify(void)
189 {
190 m_Count = 64;
191
192 m_Mode = CLASSIFY_SINGLE;
193 m_Shade_Mode = SHADE_MODE_DSC_GREY;
194
195 m_pLayer = NULL;
196 m_pColors = NULL;
197 m_pLUT = NULL;
198 }
199
200 //---------------------------------------------------------
~CWKSP_Layer_Classify(void)201 CWKSP_Layer_Classify::~CWKSP_Layer_Classify(void)
202 {}
203
204
205 ///////////////////////////////////////////////////////////
206 // //
207 // //
208 // //
209 ///////////////////////////////////////////////////////////
210
211 //---------------------------------------------------------
Initialise(CWKSP_Layer * pLayer,CSG_Table * pLUT,CSG_Colors * pColors)212 bool CWKSP_Layer_Classify::Initialise(CWKSP_Layer *pLayer, CSG_Table *pLUT, CSG_Colors *pColors)
213 {
214 m_pLayer = pLayer;
215 m_pLUT = pLUT;
216 m_pColors = pColors;
217
218 m_Count = m_pLayer->Get_Object()->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grid
219 || m_pLayer->Get_Object()->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grids
220 || m_pLayer->Get_Object()->Get_ObjectType() == SG_DATAOBJECT_TYPE_PointCloud ? 64 : 16;
221
222 //-----------------------------------------------------
223 if( m_pLUT && m_pLUT->Get_Count() == 0 )
224 {
225 CSG_Table_Record *pRecord;
226
227 pRecord = m_pLUT->Add_Record();
228 pRecord->Set_Value(LUT_COLOR , SG_GET_RGB(1, 1, 1));
229 pRecord->Set_Value(LUT_TITLE , _TL("Class 1"));
230 pRecord->Set_Value(LUT_DESCRIPTION , _TL("First Class"));
231 pRecord->Set_Value(LUT_MIN , 0.0);
232 pRecord->Set_Value(LUT_MAX , 1.0);
233
234 pRecord = m_pLUT->Add_Record();
235 pRecord->Set_Value(LUT_COLOR , SG_GET_RGB(255, 0, 0));
236 pRecord->Set_Value(LUT_TITLE , _TL("Class 2"));
237 pRecord->Set_Value(LUT_DESCRIPTION , _TL("Second Class"));
238 pRecord->Set_Value(LUT_MIN , 1.0);
239 pRecord->Set_Value(LUT_MAX , 2.0);
240 }
241
242 if( m_pLUT )
243 {
244 m_pLUT->Set_Index(LUT_MIN, TABLE_INDEX_Ascending);
245 }
246
247 return( true );
248 }
249
250
251 ///////////////////////////////////////////////////////////
252 // //
253 // //
254 // //
255 ///////////////////////////////////////////////////////////
256
257 //---------------------------------------------------------
Get_Class_Value_Minimum(int iClass)258 double CWKSP_Layer_Classify::Get_Class_Value_Minimum(int iClass)
259 {
260 switch( m_Mode )
261 {
262 case CLASSIFY_LUT:
263 if( iClass >= 0 && iClass < m_pLUT->Get_Record_Count() )
264 {
265 return( m_pLUT->Get_Record(iClass)->asDouble(LUT_MIN) );
266 }
267 break;
268
269 case CLASSIFY_GRADUATED:
270 case CLASSIFY_DISCRETE:
271 case CLASSIFY_SHADE:
272 case CLASSIFY_OVERLAY:
273 if( m_zRange > 0.0 )
274 {
275 return( Get_RelativeToMetric(iClass / (double)Get_Class_Count()) );
276 }
277 break;
278
279 default: break;
280 }
281
282 return( m_zMin );
283 }
284
Get_Class_Value_Maximum(int iClass)285 double CWKSP_Layer_Classify::Get_Class_Value_Maximum(int iClass)
286 {
287 switch( m_Mode )
288 {
289 case CLASSIFY_LUT:
290 if( iClass >= 0 && iClass < m_pLUT->Get_Record_Count() )
291 {
292 return( m_pLUT->Get_Record(iClass)->asDouble(LUT_MAX) );
293 }
294 break;
295
296 case CLASSIFY_GRADUATED:
297 case CLASSIFY_DISCRETE:
298 case CLASSIFY_SHADE:
299 case CLASSIFY_OVERLAY:
300 if( m_zRange > 0.0 )
301 {
302 return( Get_RelativeToMetric((1.0 + iClass) / (double)Get_Class_Count()) );
303 }
304 break;
305
306 default: break;
307 }
308
309 return( m_zMin + m_zRange );
310 }
311
Get_Class_Value_Center(int iClass)312 double CWKSP_Layer_Classify::Get_Class_Value_Center(int iClass)
313 {
314 switch( m_Mode )
315 {
316 case CLASSIFY_LUT:
317 if( iClass >= 0 && iClass < m_pLUT->Get_Record_Count() )
318 {
319 return( 0.5 * (m_pLUT->Get_Record(iClass)->asDouble(LUT_MIN) + m_pLUT->Get_Record(iClass)->asDouble(LUT_MAX)) );
320 }
321 break;
322
323 case CLASSIFY_GRADUATED:
324 case CLASSIFY_DISCRETE:
325 case CLASSIFY_SHADE:
326 case CLASSIFY_OVERLAY:
327 if( m_zRange > 0.0 )
328 {
329 return( Get_RelativeToMetric((0.5 + iClass) / (double)Get_Class_Count()) );
330 }
331 break;
332
333 default: break;
334 }
335
336 return( m_zMin + 0.5 * m_zRange );
337 }
338
339 //---------------------------------------------------------
Get_Class_Name(int iClass)340 wxString CWKSP_Layer_Classify::Get_Class_Name(int iClass)
341 {
342 CSG_String s;
343
344 switch( m_Mode )
345 {
346 case CLASSIFY_LUT:
347 if( iClass >= 0 && iClass < m_pLUT->Get_Record_Count() )
348 {
349 s.Printf(SG_T("%s"), m_pLUT->Get_Record(iClass)->asString(LUT_TITLE));
350 }
351 break;
352
353 case CLASSIFY_GRADUATED:
354 case CLASSIFY_DISCRETE:
355 case CLASSIFY_SHADE:
356 case CLASSIFY_OVERLAY:
357 s = SG_Get_String(Get_Class_Value_Minimum(iClass), -2) + SG_T(" < ")
358 + SG_Get_String(Get_Class_Value_Maximum(iClass), -2);
359 break;
360
361 default: break;
362 }
363
364 return( s.c_str() );
365 }
366
367 //---------------------------------------------------------
Get_Class_Name_byValue(double Value)368 wxString CWKSP_Layer_Classify::Get_Class_Name_byValue(double Value)
369 {
370 return( Get_Class_Name(Get_Class(Value)) );
371 }
372
Get_Class_Name_byValue(const wxString & Value)373 wxString CWKSP_Layer_Classify::Get_Class_Name_byValue(const wxString &Value)
374 {
375 return( SG_Data_Type_is_Numeric(m_pLUT->Get_Field_Type(LUT_MIN))
376 ? Get_Class_Name(Get_Class(CSG_String(&Value).asDouble()))
377 : Get_Class_Name(Get_Class(CSG_String(&Value)))
378 );
379 }
380
381
382 ///////////////////////////////////////////////////////////
383 // //
384 // Unique //
385 // //
386 ///////////////////////////////////////////////////////////
387
388 //---------------------------------------------------------
Set_Unique_Color(int Color)389 void CWKSP_Layer_Classify::Set_Unique_Color(int Color)
390 {
391 m_UNI_Color = Color;
392 }
393
394
395 ///////////////////////////////////////////////////////////
396 // //
397 // Metric //
398 // //
399 ///////////////////////////////////////////////////////////
400
401 //---------------------------------------------------------
Set_Class_Count(int Count)402 bool CWKSP_Layer_Classify::Set_Class_Count(int Count)
403 {
404 if( Count > 0 && Count != m_Count )
405 {
406 m_Count = Count;
407
408 return( Histogram_Update() );
409 }
410
411 return( false );
412 }
413
414 //---------------------------------------------------------
Set_Metric(int Mode,double LogFactor,double zMin,double zMax)415 void CWKSP_Layer_Classify::Set_Metric(int Mode, double LogFactor, double zMin, double zMax)
416 {
417 m_zMode = Mode;
418 m_zMin = zMin < zMax ? zMin : zMax;
419 m_zRange = zMin < zMax ? (zMax - zMin) : (zMin - zMax);
420 m_zLogRange = LogFactor;
421 m_zLogMax = log(1.0 + m_zLogRange);
422
423 if( m_zRange <= 0.0 || (m_zMode != 0 && m_zLogRange <= 0.0) )
424 {
425 m_zRange = 0.0;
426 }
427 }
428
429
430 ///////////////////////////////////////////////////////////
431 // //
432 // Lookup Table //
433 // //
434 ///////////////////////////////////////////////////////////
435
436 //---------------------------------------------------------
_LUT_Cmp_Class(double Value,int iClass)437 inline int CWKSP_Layer_Classify::_LUT_Cmp_Class(double Value, int iClass)
438 {
439 CSG_Table_Record *pClass = m_pLUT->Get_Record_byIndex(iClass);
440
441 double min = pClass->asDouble(LUT_MIN);
442
443 if( Value == min ) { return( 0 ); }
444 if( Value < min ) { return( 1 ); }
445
446 double max = pClass->asDouble(LUT_MAX);
447
448 if( max < min ) { return( -1 ); }
449 if( Value < max ) { return( 0 ); }
450
451 return( iClass == m_pLUT->Get_Count() - 1 && Value == max ? 0 : -1 );
452 }
453
454 //---------------------------------------------------------
_LUT_Get_Class(double Value)455 int CWKSP_Layer_Classify::_LUT_Get_Class(double Value)
456 {
457 int a, b, i, c;
458
459 if( m_pLUT->Get_Record_Count() > 0 )
460 {
461 if( m_pLUT->Get_Index_Field(0) != LUT_MIN || m_pLUT->Get_Index_Order(0) != TABLE_INDEX_Ascending )
462 {
463 m_pLUT->Set_Index(LUT_MIN, TABLE_INDEX_Ascending);
464 }
465
466 for(a=0, b=m_pLUT->Get_Record_Count()-1; a < b; )
467 {
468 i = a + (b - a) / 2;
469 c = _LUT_Cmp_Class(Value, i);
470
471 if( c > 0 )
472 {
473 b = b > i ? i : b - 1;
474 }
475 else if( c < 0 )
476 {
477 a = a < i ? i : a + 1;
478 }
479 else
480 {
481 return( m_pLUT->Get_Record_byIndex(i)->Get_Index() );
482 }
483 }
484
485 if( _LUT_Cmp_Class(Value, a) == 0 )
486 {
487 return( m_pLUT->Get_Record_byIndex(a)->Get_Index() );
488 }
489
490 if( a != b && _LUT_Cmp_Class(Value, b) == 0 )
491 {
492 return( m_pLUT->Get_Record_byIndex(b)->Get_Index() );
493 }
494 }
495
496 return( -1 );
497 }
498
499 //---------------------------------------------------------
_LUT_Cmp_Class(const CSG_String & Value,int iClass)500 inline int CWKSP_Layer_Classify::_LUT_Cmp_Class(const CSG_String &Value, int iClass)
501 {
502 CSG_Table_Record *pClass = m_pLUT->Get_Record_byIndex(iClass);
503
504 int c = Value.Cmp(pClass->asString(LUT_MIN));
505
506 if( c < 0 )
507 {
508 return( 1 );
509 }
510
511 if( c > 0 && Value.Cmp(pClass->asString(LUT_MAX)) > 0 )
512 {
513 return( -1 );
514 }
515
516 return( 0 );
517 }
518
519 //---------------------------------------------------------
_LUT_Get_Class(const CSG_String & Value)520 int CWKSP_Layer_Classify::_LUT_Get_Class(const CSG_String &Value)
521 {
522 int a, b, i, c;
523
524 if( m_pLUT->Get_Record_Count() > 0 )
525 {
526 if( m_pLUT->Get_Index_Field(0) != LUT_MIN || m_pLUT->Get_Index_Order(0) != TABLE_INDEX_Ascending )
527 {
528 m_pLUT->Set_Index(LUT_MIN, TABLE_INDEX_Ascending);
529 }
530
531 for(a=0, b=m_pLUT->Get_Record_Count()-1; a < b; )
532 {
533 i = a + (b - a) / 2;
534 c = _LUT_Cmp_Class(Value, i);
535
536 if( c > 0 )
537 {
538 b = b > i ? i : b - 1;
539 }
540 else if( c < 0 )
541 {
542 a = a < i ? i : a + 1;
543 }
544 else
545 {
546 return( m_pLUT->Get_Record_byIndex(i)->Get_Index() );
547 }
548 }
549
550 if( _LUT_Cmp_Class(Value, a) == 0 )
551 {
552 return( m_pLUT->Get_Record_byIndex(a)->Get_Index() );
553 }
554
555 if( a != b && _LUT_Cmp_Class(Value, b) == 0 )
556 {
557 return( m_pLUT->Get_Record_byIndex(b)->Get_Index() );
558 }
559 }
560
561 return( -1 );
562 }
563
564
565 ///////////////////////////////////////////////////////////
566 // //
567 // //
568 // //
569 ///////////////////////////////////////////////////////////
570
571 //---------------------------------------------------------
Metric2EqualElements(void)572 void CWKSP_Layer_Classify::Metric2EqualElements(void)
573 {
574 if( m_pLayer->Get_Type() == WKSP_ITEM_Grid && m_pColors->Get_Count() > 1 )
575 {
576 m_pLUT->Del_Records();
577
578 CSG_Grid *pGrid = ((CWKSP_Grid *)m_pLayer)->Get_Grid();
579
580 double zA, zB, dClass = (double)pGrid->Get_NCells() / (double)(m_pColors->Get_Count());
581
582 if( !pGrid->Set_Index() )
583 {
584 return;
585 }
586
587 int x, y;
588
589 pGrid->Get_Sorted(0, x, y, false, false);
590 zA = pGrid->asDouble(x, y);
591
592 for(int iClass=0; iClass<m_pColors->Get_Count()-1; iClass++)
593 {
594 pGrid->Get_Sorted((sLong)(dClass * (iClass + 1.0)), x, y, false, false);
595 zB = zA;
596 zA = pGrid->asDouble(x, y);
597
598 CSG_Table_Record *pClass = m_pLUT->Add_Record();
599 pClass->Set_Value(LUT_COLOR , m_pColors->Get_Color(iClass));
600 pClass->Set_Value(LUT_TITLE , CSG_String::Format(">=%f" , zB ));
601 pClass->Set_Value(LUT_DESCRIPTION, CSG_String::Format("%f <-> %f", zB, zA));
602 pClass->Set_Value(LUT_MIN , zB);
603 pClass->Set_Value(LUT_MAX , zA);
604 }
605
606 pGrid->Get_Sorted(pGrid->Get_NCells() - 1, x, y, false, false);
607 zB = zA;
608 zA = pGrid->asDouble(x, y);
609
610 CSG_Table_Record *pClass = m_pLUT->Add_Record();
611 pClass->Set_Value(LUT_COLOR , m_pColors->Get_Color(m_pColors->Get_Count() - 1));
612 pClass->Set_Value(LUT_TITLE , CSG_String::Format(">=%f" , zB ));
613 pClass->Set_Value(LUT_DESCRIPTION, CSG_String::Format("%f <-> %f", zB, zA));
614 pClass->Set_Value(LUT_MIN , zB);
615 pClass->Set_Value(LUT_MAX , zA);
616
617 Set_Mode(CLASSIFY_LUT);
618 m_pLayer->Update_Views();
619 }
620 }
621
622
623 ///////////////////////////////////////////////////////////
624 // //
625 // Histogram //
626 // //
627 ///////////////////////////////////////////////////////////
628
629 //---------------------------------------------------------
Histogram_Update(void)630 bool CWKSP_Layer_Classify::Histogram_Update(void)
631 {
632 m_Statistics.Create();
633
634 if( Get_Class_Count() < 1 )
635 {
636 m_Histogram.Destroy();
637
638 return( false );
639 }
640
641 //-----------------------------------------------------
642 STATUSBAR_Set_Text(_TL("Build Histogram..."));
643
644 m_Histogram.Create(Get_Class_Count(), 0, Get_Class_Count() - 1);
645
646 switch( m_pLayer->Get_Type() )
647 {
648 case WKSP_ITEM_Grid:
649 _Histogram_Update(((CWKSP_Grid *)m_pLayer)->Get_Grid ());
650 break;
651
652 case WKSP_ITEM_Grids:
653 if( m_Mode == CLASSIFY_OVERLAY )
654 {
655 _Histogram_Update(((CWKSP_Grids *)m_pLayer)->Get_Grids());
656 }
657 else
658 {
659 _Histogram_Update(((CWKSP_Grids *)m_pLayer)->Get_Grid ());
660 }
661 break;
662
663 case WKSP_ITEM_Shapes:
664 _Histogram_Update(((CWKSP_Shapes *)m_pLayer)->Get_Shapes(),
665 ((CWKSP_Shapes *)m_pLayer)->Get_Field_Value (),
666 ((CWKSP_Shapes *)m_pLayer)->Get_Field_Normal(),
667 ((CWKSP_Shapes *)m_pLayer)->Get_Scale_Normal()
668 );
669 break;
670
671 case WKSP_ITEM_PointCloud:
672 _Histogram_Update(((CWKSP_PointCloud *)m_pLayer)->Get_PointCloud(),
673 ((CWKSP_PointCloud *)m_pLayer)->Get_Field_Value()
674 );
675 break;
676
677 default: break;
678 }
679
680 m_Histogram.Update();
681
682 PROCESS_Set_Okay();
683
684 //-----------------------------------------------------
685 return( true );
686 }
687
688 //---------------------------------------------------------
_Histogram_Update(CSG_Grid * pGrid)689 bool CWKSP_Layer_Classify::_Histogram_Update(CSG_Grid *pGrid)
690 {
691 if( pGrid->Get_Max_Samples() > 0 && pGrid->Get_Max_Samples() < pGrid->Get_NCells() )
692 {
693 double d = (double)pGrid->Get_NCells() / (double)pGrid->Get_Max_Samples();
694
695 for(double i=0; i<(double)pGrid->Get_NCells() && PROGRESSBAR_Set_Position(i, (double)pGrid->Get_NCells()); i+=d)
696 {
697 if( !pGrid->is_NoData((sLong)i) )
698 {
699 m_Histogram += Get_Class(pGrid->asDouble((sLong)i));
700 }
701 }
702
703 if( m_Histogram.Update() && m_Histogram.Get_Element_Count() < pGrid->Get_Max_Samples() ) // any no-data cells ?
704 {
705 d *= (double)m_Histogram.Get_Element_Count() / (double)pGrid->Get_Max_Samples();
706 }
707
708 m_Histogram.Scale_Element_Count(d);
709
710 m_Statistics = pGrid->Get_Statistics();
711
712 return( true );
713 }
714
715 for(sLong i=0; i<pGrid->Get_NCells() && PROGRESSBAR_Set_Position((double)i, (double)pGrid->Get_NCells()); i++)
716 {
717 if( !pGrid->is_NoData(i) )
718 {
719 m_Histogram += Get_Class(pGrid->asDouble(i));
720 }
721 }
722
723 m_Statistics = pGrid->Get_Statistics();
724
725 return( true );
726 }
727
728 //---------------------------------------------------------
_Histogram_Update(CSG_Grids * pGrids)729 bool CWKSP_Layer_Classify::_Histogram_Update(CSG_Grids *pGrids)
730 {
731 if( pGrids->Get_Max_Samples() > 0 && pGrids->Get_Max_Samples() < pGrids->Get_NCells() )
732 {
733 double d = (double)pGrids->Get_NCells() / (double)pGrids->Get_Max_Samples();
734
735 for(double i=0; i<(double)pGrids->Get_NCells() && PROGRESSBAR_Set_Position(i, (double)pGrids->Get_NCells()); i+=d)
736 {
737 if( !pGrids->is_NoData((sLong)i) )
738 {
739 m_Histogram += Get_Class(pGrids->asDouble((sLong)i));
740 }
741 }
742
743 if( m_Histogram.Update() && m_Histogram.Get_Element_Count() < pGrids->Get_Max_Samples() ) // any no-data cells ?
744 {
745 d *= (double)m_Histogram.Get_Element_Count() / (double)pGrids->Get_Max_Samples();
746 }
747
748 m_Histogram.Scale_Element_Count(d);
749
750 m_Statistics = pGrids->Get_Statistics();
751
752 return( true );
753 }
754
755 for(sLong i=0; i<pGrids->Get_NCells() && PROGRESSBAR_Set_Position((double)i, (double)pGrids->Get_NCells()); i++)
756 {
757 if( !pGrids->is_NoData(i) )
758 {
759 m_Histogram += Get_Class(pGrids->asDouble(i));
760 }
761 }
762
763 m_Statistics = pGrids->Get_Statistics();
764
765 return( true );
766 }
767
768 //---------------------------------------------------------
_Histogram_Update(CSG_Shapes * pShapes,int Attribute,int Normalize,double Scale)769 bool CWKSP_Layer_Classify::_Histogram_Update(CSG_Shapes *pShapes, int Attribute, int Normalize, double Scale)
770 {
771 if( Attribute < 0 || Attribute >= pShapes->Get_Field_Count() )
772 {
773 return( false );
774 }
775
776 if( pShapes->Get_Max_Samples() > 0 && pShapes->Get_Max_Samples() < pShapes->Get_Count() )
777 {
778 double d = (double)pShapes->Get_Count() / (double)pShapes->Get_Max_Samples();
779
780 for(double i=0; i<(double)pShapes->Get_Count() && PROGRESSBAR_Set_Position(i, (double)pShapes->Get_Count()); i+=d)
781 {
782 CSG_Shape *pShape = pShapes->Get_Shape((int)i);
783
784 if( m_Mode == CLASSIFY_LUT )
785 {
786 m_Histogram += SG_Data_Type_is_Numeric(m_pLUT->Get_Field_Type(LUT_MIN))
787 ? Get_Class(pShape->asDouble(Attribute))
788 : Get_Class(pShape->asString(Attribute));
789 }
790 else if( !pShape->is_NoData(Attribute) )
791 {
792 double z = pShape->asDouble(Attribute);
793
794 if( Normalize < 0 )
795 {
796 m_Histogram += Get_Class(z); m_Statistics += z;
797 }
798 else if( !pShape->is_NoData(Normalize) && pShape->asDouble(Normalize) )
799 {
800 z *= Scale / pShape->asDouble(Normalize);
801
802 m_Histogram += Get_Class(z); m_Statistics += z;
803 }
804 }
805 }
806
807 if( m_Histogram.Update() && m_Histogram.Get_Element_Count() < pShapes->Get_Max_Samples() ) // any no-data cells ?
808 {
809 d *= (double)m_Histogram.Get_Element_Count() / (double)pShapes->Get_Max_Samples();
810 }
811
812 m_Histogram.Scale_Element_Count(d);
813
814 return( true );
815 }
816
817 for(int i=0; i<pShapes->Get_Count() && PROGRESSBAR_Set_Position(i, pShapes->Get_Count()); i++)
818 {
819 CSG_Shape *pShape = pShapes->Get_Shape(i);
820
821 if( m_Mode == CLASSIFY_LUT )
822 {
823 m_Histogram += SG_Data_Type_is_Numeric(m_pLUT->Get_Field_Type(LUT_MIN))
824 ? Get_Class(pShape->asDouble(Attribute))
825 : Get_Class(pShape->asString(Attribute));
826 }
827 else if( !pShape->is_NoData(Attribute) )
828 {
829 double z = pShape->asDouble(Attribute);
830
831 if( Normalize < 0 )
832 {
833 m_Histogram += Get_Class(z); m_Statistics += z;
834 }
835 else if( !pShape->is_NoData(Normalize) && pShape->asDouble(Normalize) )
836 {
837 z *= Scale / pShape->asDouble(Normalize);
838
839 m_Histogram += Get_Class(z); m_Statistics += z;
840 }
841 }
842 }
843
844 return( true );
845 }
846
847
848 ///////////////////////////////////////////////////////////
849 // //
850 // //
851 // //
852 ///////////////////////////////////////////////////////////
853
854 //---------------------------------------------------------
855