1
2 ///////////////////////////////////////////////////////////
3 // //
4 // SAGA //
5 // //
6 // System for Automated Geoscientific Analyses //
7 // //
8 // Tool Library //
9 // ta_morphometry //
10 // //
11 //-------------------------------------------------------//
12 // //
13 // fuzzy_landform_elements.h //
14 // //
15 // Copyright (C) 2013 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 Hamburg //
44 // Germany //
45 // //
46 ///////////////////////////////////////////////////////////
47
48 //---------------------------------------------------------
49 #include "fuzzy_landform_elements.h"
50
51
52 ///////////////////////////////////////////////////////////
53 // //
54 // //
55 // //
56 ///////////////////////////////////////////////////////////
57
58 //---------------------------------------------------------
59 enum
60 {
61 SLOPE = 0,
62 MINCURV,
63 MAXCURV,
64 PCURV,
65 TCURV,
66 IN_COUNT
67 };
68
69 //---------------------------------------------------------
70 const CSG_String IN_Type[IN_COUNT][2] =
71 {
72 { "SLOPE" , _TL("Slope" ) },
73 { "MINCURV" , _TL("Minimum Curvature" ) },
74 { "MAXCURV" , _TL("Maximum Curvature" ) },
75 { "PCURV" , _TL("Profile Curvature" ) },
76 { "TCURV" , _TL("Tangential Curvature") }
77 };
78
79
80 ///////////////////////////////////////////////////////////
81 // //
82 ///////////////////////////////////////////////////////////
83
84 //---------------------------------------------------------
85 struct SForm_Def
86 {
87 CSG_String ID, Name;
88
89 long Color;
90
91 int Value;
92 };
93
94 //---------------------------------------------------------
95 enum
96 {
97 PLAIN = 0,
98 PIT,
99 PEAK,
100 RIDGE,
101 CHANNEL,
102 SADDLE,
103 BSLOPE,
104 FSLOPE,
105 SSLOPE,
106 HOLLOW,
107 FHOLLOW,
108 SHOLLOW,
109 SPUR,
110 FSPUR,
111 SSPUR,
112 FE_COUNT
113 };
114
115 //---------------------------------------------------------
116 const struct SForm_Def Form_Def[FE_COUNT] =
117 {
118 { "PLAIN" , _TL("Plain" ), SG_GET_RGB(220, 220, 220), 100 },
119 { "PIT" , _TL("Pit" ), SG_GET_RGB( 0, 0, 100), 111 },
120 { "PEAK" , _TL("Peak" ), SG_GET_RGB(100, 0, 0), 122 },
121 { "RIDGE" , _TL("Ridge" ), SG_GET_RGB(200, 0, 0), 120 },
122 { "CHANNEL" , _TL("Channel" ), SG_GET_RGB( 0, 0, 255), 101 },
123 { "SADDLE" , _TL("Saddle" ), SG_GET_RGB( 0, 200, 255), 121 },
124 { "BSLOPE" , _TL("Back Slope" ), SG_GET_RGB(255, 255, 0), 0 },
125 { "FSLOPE" , _TL("Foot Slope" ), SG_GET_RGB(240, 220, 0), 10 },
126 { "SSLOPE" , _TL("Shoulder Slope" ), SG_GET_RGB(255, 255, 150), 20 },
127 { "HOLLOW" , _TL("Hollow" ), SG_GET_RGB(180, 230, 0), 1 },
128 { "FHOLLOW" , _TL("Foot Hollow" ), SG_GET_RGB(100, 230, 0), 11 },
129 { "SHOLLOW" , _TL("Shoulder Hollow"), SG_GET_RGB(180, 255, 0), 21 },
130 { "SPUR" , _TL("Spur" ), SG_GET_RGB(250, 210, 0), 2 },
131 { "FSPUR" , _TL("Foot Spur" ), SG_GET_RGB(250, 170, 0), 12 },
132 { "SSPUR" , _TL("Shoulder Spur" ), SG_GET_RGB(255, 120, 0), 22 }
133 };
134
135
136 ///////////////////////////////////////////////////////////
137 // //
138 // //
139 // //
140 ///////////////////////////////////////////////////////////
141
142 //---------------------------------------------------------
CFuzzy_Landform_Elements(void)143 CFuzzy_Landform_Elements::CFuzzy_Landform_Elements(void)
144 {
145 Set_Name (_TL("Fuzzy Landform Element Classification"));
146
147 Set_Author ("O.Conrad (c) 2013");
148
149 Set_Description (_TW(
150 "Algorithm for derivation of form elements according to slope, maximum curvature, "
151 "minimum curvature, profile curvature, tangential curvature, "
152 "based on a linear semantic import model for slope and curvature and a fuzzy classification "
153 "Based on the AML script \'felementf\' by Jochen Schmidt, Landcare Research. "
154 ));
155
156 Add_Reference("Schmidt, J. & Hewitt, A.", "2004",
157 "Fuzzy land element classification from DTMs based on geometry and terrain position",
158 "Geoderma, 121(3-4), 243-256.",
159 SG_T("http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.472.3485&rep=rep1&type=pdf"), SG_T("CiteSeerX")
160 // SG_T("https://www.sciencedirect.com/science/article/pii/S0016706103003720"), SG_T("ScienceDirect")
161 );
162
163 //-----------------------------------------------------
164 int i;
165
166 Parameters.Add_Grid("", "ELEVATION", _TL("Elevation" ), _TL(""), PARAMETER_INPUT);
167
168 for(i=0; i<IN_COUNT; i++)
169 {
170 Parameters.Add_Grid("", IN_Type [i][0], IN_Type[i][1] , _TL(""), PARAMETER_INPUT);
171 }
172
173 Parameters.Add_Grid("", "FORM" , _TL("Landform" ), _TL(""), PARAMETER_OUTPUT);
174 Parameters.Add_Grid("", "MEM" , _TL("Maximum Membership"), _TL(""), PARAMETER_OUTPUT_OPTIONAL);
175 Parameters.Add_Grid("", "ENTROPY" , _TL("Entropy" ), _TL(""), PARAMETER_OUTPUT_OPTIONAL);
176 Parameters.Add_Grid("", "CI" , _TL("Confusion Index" ), _TL(""), PARAMETER_OUTPUT_OPTIONAL);
177
178 for(i=0; i<FE_COUNT; i++)
179 {
180 Parameters.Add_Grid("", Form_Def[i].ID, Form_Def[i].Name, _TL(""), PARAMETER_OUTPUT_OPTIONAL);
181 }
182
183 //-----------------------------------------------------
184 Parameters.Add_Choice("",
185 "INPUT" , _TL("Input"),
186 _TL("if elevation is selected, slopes and curvatures will be calculated internally"),
187 CSG_String::Format("%s|%s",
188 _TL("elevation"),
189 _TL("slope and curvatures")
190 ), 0
191 );
192
193 Parameters.Add_Bool("",
194 "MEMBERSHIP", _TL("Memberships"),
195 _TL(""),
196 false
197 );
198
199 Parameters.Add_Choice("SLOPE",
200 "SLOPETODEG", _TL("Slope Grid Units"),
201 _TL(""),
202 CSG_String::Format("%s|%s",
203 _TL("degree"),
204 _TL("radians")
205 ), 0
206 );
207
208 Parameters.Add_Range("",
209 "T_SLOPE" , _TL("Slope Thresholds [Degree]"),
210 _TL("lower and upper thresholds for semantic import model, planar vs. sloped areas"),
211 2., 7., 0., true, 90., true
212 );
213
214 Parameters.Add_Range("",
215 "T_CURVE" , _TL("Curvature Thresholds [1000 / m]"),
216 _TL("lower and upper thresholds for semantic import model, straight vs. curved areas"),
217 0.02, 0.5
218 );
219 }
220
221
222 ///////////////////////////////////////////////////////////
223 // //
224 ///////////////////////////////////////////////////////////
225
226 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)227 int CFuzzy_Landform_Elements::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
228 {
229 if( pParameter->Cmp_Identifier("INPUT") )
230 {
231 for(int i=0; i<IN_COUNT; i++)
232 {
233 pParameters->Set_Enabled(IN_Type[i][0], pParameter->asInt() == 1);
234 }
235
236 pParameters->Set_Enabled("ELEVATION", pParameter->asInt() == 0);
237 }
238
239 if( pParameter->Cmp_Identifier("MEMBERSHIP") )
240 {
241 for(int i=0; i<FE_COUNT; i++)
242 {
243 pParameters->Set_Enabled(Form_Def[i].ID, pParameter->asBool());
244 }
245 }
246
247 return( CSG_Tool_Grid::On_Parameters_Enable(pParameters, pParameter) );
248 }
249
250
251 ///////////////////////////////////////////////////////////
252 // //
253 ///////////////////////////////////////////////////////////
254
255 //---------------------------------------------------------
On_Execute(void)256 bool CFuzzy_Landform_Elements::On_Execute(void)
257 {
258 int i;
259 CSG_Grid *pInput[IN_COUNT], _Input[IN_COUNT], *pMembership[FE_COUNT], *pForm, *pMem, *pEntropy, *pCI;
260
261 //-----------------------------------------------------
262 if( Parameters("INPUT")->asInt() == 0 ) // elevation
263 {
264 CSG_Grid Aspect; Aspect.Create(Get_System());
265
266 for(i=0; i<IN_COUNT; i++)
267 {
268 _Input[i].Create(Get_System());
269
270 pInput[i] = &_Input[i];
271 }
272
273 CSG_Tool *pTool = SG_Get_Tool_Library_Manager().Create_Tool("ta_morphometry", 0); // Slope, Aspect, Curvatures
274
275 pTool->Set_Manager(NULL);
276
277 if( !pTool
278 || !pTool->Set_Parameter("ELEVATION" , Parameters("ELEVATION"))
279 || !pTool->Set_Parameter("ASPECT" , &Aspect)
280 || !pTool->Set_Parameter("SLOPE" , pInput[SLOPE ])
281 || !pTool->Set_Parameter("C_PROF" , pInput[PCURV ])
282 || !pTool->Set_Parameter("C_TANG" , pInput[TCURV ])
283 || !pTool->Set_Parameter("C_MINI" , pInput[MINCURV])
284 || !pTool->Set_Parameter("C_MAXI" , pInput[MAXCURV])
285 || !pTool->Set_Parameter("UNIT_SLOPE", 1) // degree
286 || !pTool->Execute() )
287 {
288 SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
289
290 return( false );
291 }
292
293 SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
294
295 m_bToDegree = false;
296 }
297 else
298 {
299 for(i=0; i<IN_COUNT; i++)
300 {
301 pInput[i] = Parameters(IN_Type[i][0])->asGrid();
302 }
303
304 m_bToDegree = Parameters("SLOPETODEG")->asInt() == 1;
305 }
306
307 //-----------------------------------------------------
308 m_loSlope = Parameters("T_SLOPE.MIN")->asDouble();// * M_DEG_TO_RAD;
309 m_hiSlope = Parameters("T_SLOPE.MAX")->asDouble();// * M_DEG_TO_RAD;
310
311 m_loCurve = Parameters("T_CURVE.MIN")->asDouble() / 1000.;
312 m_hiCurve = Parameters("T_CURVE.MAX")->asDouble() / 1000.;
313
314 //-----------------------------------------------------
315 pForm = Parameters("FORM" )->asGrid();
316 pMem = Parameters("MEM" )->asGrid();
317 pEntropy = Parameters("ENTROPY")->asGrid();
318 pCI = Parameters("CI" )->asGrid();
319
320 for(i=0; i<FE_COUNT; i++)
321 {
322 pMembership[i] = Parameters("MEMBERSHIP")->asBool() ? Parameters(Form_Def[i].ID)->asGrid() : NULL;
323
324 DataObject_Set_Colors(pMembership[i], 11, SG_COLORS_WHITE_RED);
325 }
326
327 //-----------------------------------------------------
328 CSG_Parameter *pLUT = DataObject_Get_Parameter(pForm, "LUT");
329
330 if( pLUT && pLUT->asTable() )
331 {
332 pLUT->asTable()->Del_Records();
333
334 for(i=0; i<FE_COUNT; i++)
335 {
336 CSG_Table_Record *pRecord = pLUT->asTable()->Add_Record();
337
338 pRecord->Set_Value(0, Form_Def[i].Color);
339 pRecord->Set_Value(1, Form_Def[i].Name );
340 pRecord->Set_Value(3, Form_Def[i].Value);
341 pRecord->Set_Value(4, Form_Def[i].Value);
342 }
343
344 DataObject_Set_Parameter(pForm, pLUT);
345
346 DataObject_Set_Parameter(pForm, "COLORS_TYPE", 1); // Color Classification Type: Lookup Table
347 }
348
349 //-----------------------------------------------------
350 for(int y=0; y<Get_NY() && Set_Progress(y); y++)
351 {
352 #pragma omp parallel for private(i)
353 for(int x=0; x<Get_NX(); x++)
354 {
355 bool bOkay;
356 int Element;
357 double MaxMem, Entropy, CI, Input[IN_COUNT], Membership[FE_COUNT];
358
359 for(i=0, bOkay=true; i<IN_COUNT && bOkay; i++)
360 {
361 if( pInput[i]->is_NoData(x, y) )
362 {
363 bOkay = false;
364 }
365 else
366 {
367 Input[i] = pInput[i]->asDouble(x, y);
368 }
369 }
370
371 if( bOkay && Get_Memberships(Input, Membership, Element, MaxMem, Entropy, CI) )
372 {
373 if( pForm ) pForm ->Set_Value(x, y, Element); // hard classification according to highest membership value
374 if( pMem ) pMem ->Set_Value(x, y, MaxMem );
375 if( pEntropy ) pEntropy->Set_Value(x, y, Entropy);
376 if( pCI ) pCI ->Set_Value(x, y, CI ); // confusion index
377
378 for(i=0; i<FE_COUNT; i++)
379 {
380 if( pMembership[i] ) pMembership[i]->Set_Value(x, y, Membership[i]);
381 }
382 }
383 else
384 {
385 if( pForm ) pForm ->Set_NoData(x, y);
386 if( pMem ) pMem ->Set_NoData(x, y);
387 if( pEntropy ) pEntropy->Set_NoData(x, y);
388 if( pCI ) pCI ->Set_NoData(x, y);
389
390 for(i=0; i<FE_COUNT; i++)
391 {
392 if( pMembership[i] ) pMembership[i]->Set_NoData(x, y);
393 }
394 }
395 }
396 }
397
398 //-----------------------------------------------------
399 return( true );
400 }
401
402
403 ///////////////////////////////////////////////////////////
404 // //
405 ///////////////////////////////////////////////////////////
406
407 //---------------------------------------------------------
408 #define GET_MINIMUM(a, b, c) M_GET_MIN(a, M_GET_MIN(b, c))
409
410 //---------------------------------------------------------
Get_Memberships(double Input[],double M[],int & Element,double & MaxMem,double & Entropy,double & CI)411 bool CFuzzy_Landform_Elements::Get_Memberships(double Input[], double M[], int &Element, double &MaxMem, double &Entropy, double &CI)
412 {
413 double bFlat, bSlope, MaxMem2,
414 bPCurve , bPCurveX , bPCurveV,
415 bTCurve , bTCurveX , bTCurveV,
416 bMaxCurve, bMaxCurveX, bMaxCurveV,
417 bMinCurve, bMinCurveX, bMinCurveV;
418
419 //-----------------------------------------------------
420 if( m_bToDegree )
421 {
422 Input[SLOPE] *= M_RAD_TO_DEG;
423 }
424
425 //-----------------------------------------------------
426 // membership slope flat
427 bFlat = Input[SLOPE] <= m_loSlope ? 1.0 : (Input[SLOPE] >= m_hiSlope ? 0.0
428 : (m_hiSlope - Input[SLOPE]) / (m_hiSlope - m_loSlope)); // linear membership fct
429 bSlope = 1 - bFlat;
430
431 // membership pcurv straight
432 bPCurve = fabs(Input[PCURV]) <= m_loCurve ? 1.0 : (fabs(Input[PCURV]) >= m_hiCurve ? 0.0
433 : (m_hiCurve - fabs(Input[PCURV])) / (m_hiCurve - m_loCurve)); // linear membership fct
434 bPCurveX = Input[PCURV] >= 0.0 ? 1.0 - bPCurve : 0.0;
435 bPCurveV = Input[PCURV] <= 0.0 ? 1.0 - bPCurve : 0.0;
436
437 // membership tcurv straight
438 bTCurve = fabs(Input[TCURV]) <= m_loCurve ? 1.0 : (fabs(Input[TCURV]) >= m_hiCurve ? 0.0
439 : (m_hiCurve - fabs(Input[TCURV])) / (m_hiCurve - m_loCurve)); // linear membership fct
440 bTCurveX = Input[TCURV] >= 0.0 ? 1.0 - bTCurve : 0.0;
441 bTCurveV = Input[TCURV] <= 0.0 ? 1.0 - bTCurve : 0.0;
442
443 // membership maxcurv straight
444 bMaxCurve = fabs(Input[MAXCURV]) <= m_loCurve ? 1.0 : (fabs(Input[MAXCURV]) >= m_hiCurve ? 0.0
445 : (m_hiCurve - fabs(Input[MAXCURV])) / (m_hiCurve - m_loCurve)); // linear membership fct
446 bMaxCurveX = Input[MAXCURV] >= 0.0 ? 1.0 - bMaxCurve : 0.0;
447 bMaxCurveV = Input[MAXCURV] <= 0.0 ? 1.0 - bMaxCurve : 0.0;
448
449 // membership mincurv straight
450 bMinCurve = fabs(Input[MINCURV]) <= m_loCurve ? 1.0 : (fabs(Input[MINCURV]) >= m_hiCurve ? 0.0
451 : (m_hiCurve - fabs(Input[MINCURV])) / (m_hiCurve - m_loCurve)); // linear membership fct
452 bMinCurveX = Input[MINCURV] >= 0.0 ? 1.0 - bMinCurve : 0.0;
453 bMinCurveV = Input[MINCURV] <= 0.0 ? 1.0 - bMinCurve : 0.0;
454
455 //-----------------------------------------------------
456 M[PLAIN] = GET_MINIMUM(bFlat, bMaxCurve, bMinCurve);
457 Element = Form_Def[PLAIN].Value;
458 MaxMem = M[PLAIN];
459
460 M[PIT] = GET_MINIMUM(bFlat, bMaxCurveV, bMinCurveV);
461 if( M[PIT] > MaxMem )
462 {
463 Element = Form_Def[PIT].Value;
464 MaxMem = M[PIT];
465 MaxMem2 = M[PLAIN];
466 }
467 else
468 {
469 MaxMem2 = M[PIT];
470 }
471
472 M[PEAK] = GET_MINIMUM(bFlat, bMaxCurveX, bMinCurveX);
473 if( M[PEAK] > MaxMem )
474 {
475 Element = Form_Def[PEAK].Value;
476 MaxMem = M[PEAK];
477 }
478 else if( M[PEAK] > MaxMem2 )
479 {
480 MaxMem2 = M[PEAK];
481 }
482
483 M[RIDGE] = GET_MINIMUM(bFlat, bMaxCurveX, bMinCurve);
484 if( M[RIDGE] > MaxMem )
485 {
486 Element = Form_Def[RIDGE].Value;
487 MaxMem = M[RIDGE];
488 }
489 else if( M[RIDGE] > MaxMem2 )
490 {
491 MaxMem2 = M[RIDGE];
492 }
493
494 M[CHANNEL] = GET_MINIMUM(bFlat, bMaxCurve, bMinCurveV);
495 if( M[CHANNEL] > MaxMem )
496 {
497 Element = Form_Def[CHANNEL].Value;
498 MaxMem = M[CHANNEL];
499 }
500 else if( M[CHANNEL] > MaxMem2 )
501 {
502 MaxMem2 = M[CHANNEL];
503 }
504
505 M[SADDLE] = GET_MINIMUM(bFlat, bMaxCurveX, bMinCurveV);
506 if( M[SADDLE] > MaxMem )
507 {
508 Element = Form_Def[SADDLE].Value;
509 MaxMem = M[SADDLE];
510 }
511 else if( M[SADDLE] > MaxMem2 )
512 {
513 MaxMem2 = M[SADDLE];
514 }
515
516 M[BSLOPE] = GET_MINIMUM(bSlope, bPCurve, bTCurve);
517 if( M[BSLOPE] > MaxMem )
518 {
519 Element = Form_Def[BSLOPE].Value;
520 MaxMem = M[BSLOPE];
521 }
522 else if( M[BSLOPE] > MaxMem2 )
523 {
524 MaxMem2 = M[BSLOPE];
525 }
526
527 M[FSLOPE] = GET_MINIMUM(bSlope, bPCurveV, bTCurve);
528 if( M[FSLOPE] > MaxMem )
529 {
530 Element = Form_Def[FSLOPE].Value;
531 MaxMem = M[FSLOPE];
532 }
533 else if( M[FSLOPE] > MaxMem2 )
534 {
535 MaxMem2 = M[FSLOPE];
536 }
537
538 M[SSLOPE] = GET_MINIMUM(bSlope, bPCurveX, bTCurve);
539 if( M[SSLOPE] > MaxMem )
540 {
541 Element = Form_Def[SSLOPE].Value;
542 MaxMem = M[SSLOPE];
543 }
544 else if( M[SSLOPE] > MaxMem2 )
545 {
546 MaxMem2 = M[SSLOPE];
547 }
548
549 M[HOLLOW] = GET_MINIMUM(bSlope, bPCurve, bTCurveV);
550 if( M[HOLLOW] > MaxMem )
551 {
552 Element = Form_Def[HOLLOW].Value;
553 MaxMem = M[HOLLOW];
554 }
555 else if( M[HOLLOW] > MaxMem2 )
556 {
557 MaxMem2 = M[HOLLOW];
558 }
559
560 M[FHOLLOW] = GET_MINIMUM(bSlope, bPCurveV, bTCurveV);
561 if( M[FHOLLOW] > MaxMem )
562 {
563 Element = Form_Def[FHOLLOW].Value;
564 MaxMem = M[FHOLLOW];
565 }
566 else if( M[FHOLLOW] > MaxMem2 )
567 {
568 MaxMem2 = M[FHOLLOW];
569 }
570
571 M[SHOLLOW] = GET_MINIMUM(bSlope, bPCurveX, bTCurveV);
572 if( M[SHOLLOW] > MaxMem )
573 {
574 Element = Form_Def[SHOLLOW].Value;
575 MaxMem = M[SHOLLOW];
576 }
577 else if( M[SHOLLOW] > MaxMem2 )
578 {
579 MaxMem2 = M[SHOLLOW];
580 }
581
582 M[SPUR] = GET_MINIMUM(bSlope, bPCurve, bTCurveX);
583 if( M[SPUR] > MaxMem )
584 {
585 Element = Form_Def[SPUR].Value;
586 MaxMem = M[SPUR];
587 }
588 else if( M[SPUR] > MaxMem2 )
589 {
590 MaxMem2 = M[SPUR];
591 }
592
593 M[FSPUR] = GET_MINIMUM(bSlope, bPCurveV, bTCurveX);
594 if( M[FSPUR] > MaxMem )
595 {
596 Element = Form_Def[FSPUR].Value;
597 MaxMem = M[FSPUR];
598 }
599 else if( M[FSPUR] > MaxMem2 )
600 {
601 MaxMem2 = M[FSPUR];
602 }
603
604 M[SSPUR] = GET_MINIMUM(bSlope, bPCurveX, bTCurveX);
605 if( M[SSPUR] > MaxMem )
606 {
607 Element = Form_Def[SSPUR].Value;
608 MaxMem = M[SSPUR];
609 }
610 else if( M[SSPUR] > MaxMem2 )
611 {
612 MaxMem2 = M[SSPUR];
613 }
614
615 //-----------------------------------------------------
616 double summem = 0.0; // = %PLAIN% + %PIT% + %PEAK% + %RIDGE% + %CHANNEL% + %SADDLE% + %BSLOPE% + %FSLOPE% + %SSLOPE% + %HOLLOW% + %FHOLLOW% + %SHOLLOW% + %SPUR% + %FSPUR% + %SSPUR%
617
618 for(int i=0; i<FE_COUNT; i++)
619 {
620 summem += M[i];
621 }
622
623 // entropy: / ln (15 elements)
624 Entropy = -0.3692693 *
625 ( (M[PLAIN] <= 0 || summem <= 0 ? 0 : M[PLAIN] * log(M[PLAIN] ) / summem)
626 + (M[PIT] <= 0 || summem <= 0 ? 0 : M[PIT] * log(M[PIT] ) / summem)
627 + (M[PEAK] <= 0 || summem <= 0 ? 0 : M[PEAK] * log(M[PEAK] ) / summem)
628 + (M[RIDGE] <= 0 || summem <= 0 ? 0 : M[RIDGE] * log(M[RIDGE] ) / summem)
629 + (M[CHANNEL] <= 0 || summem <= 0 ? 0 : M[CHANNEL] * log(M[CHANNEL]) / summem)
630 + (M[SADDLE] <= 0 || summem <= 0 ? 0 : M[SADDLE] * log(M[SADDLE] ) / summem)
631 + (M[BSLOPE] <= 0 || summem <= 0 ? 0 : M[BSLOPE] * log(M[BSLOPE] ) / summem)
632 + (M[FSLOPE] <= 0 || summem <= 0 ? 0 : M[FSLOPE] * log(M[FSLOPE] ) / summem)
633 + (M[SSLOPE] <= 0 || summem <= 0 ? 0 : M[SSLOPE] * log(M[SSLOPE] ) / summem)
634 + (M[HOLLOW] <= 0 || summem <= 0 ? 0 : M[HOLLOW] * log(M[HOLLOW] ) / summem)
635 + (M[FHOLLOW] <= 0 || summem <= 0 ? 0 : M[FHOLLOW] * log(M[FHOLLOW]) / summem)
636 + (M[SHOLLOW] <= 0 || summem <= 0 ? 0 : M[SHOLLOW] * log(M[SHOLLOW]) / summem)
637 + (M[SPUR] <= 0 || summem <= 0 ? 0 : M[SPUR] * log(M[SPUR] ) / summem)
638 + (M[FSPUR] <= 0 || summem <= 0 ? 0 : M[FSPUR] * log(M[FSPUR] ) / summem)
639 + (M[SSPUR] <= 0 || summem <= 0 ? 0 : M[SSPUR] * log(M[SSPUR] ) / summem)
640 - (summem <= 0 ? 0 : log(summem))
641 );
642
643 CI = MaxMem2 / MaxMem; // confusion index
644
645 //-----------------------------------------------------
646 return( true );
647 }
648
649
650 ///////////////////////////////////////////////////////////
651 // //
652 // //
653 // //
654 ///////////////////////////////////////////////////////////
655
656 //---------------------------------------------------------
657