1 /**********************************************************
2  * Version $Id$
3  *********************************************************/
4 
5 ///////////////////////////////////////////////////////////
6 //                                                       //
7 //                         SAGA                          //
8 //                                                       //
9 //      System for Automated Geoscientific Analyses      //
10 //                                                       //
11 //                     Tool Library                      //
12 //                   pointcloud_tools                    //
13 //                                                       //
14 //-------------------------------------------------------//
15 //                                                       //
16 //                 pc_reclass_extract.cpp                //
17 //                                                       //
18 //                 Copyright (C) 2009 by                 //
19 //                    Volker Wichmann                    //
20 //                                                       //
21 //-------------------------------------------------------//
22 //                                                       //
23 // This file is part of 'SAGA - System for Automated     //
24 // Geoscientific Analyses'. SAGA is free software; you   //
25 // can redistribute it and/or modify it under the terms  //
26 // of the GNU General Public License as published by the //
27 // Free Software Foundation, either version 2 of the     //
28 // License, or (at your option) any later version.       //
29 //                                                       //
30 // SAGA is distributed in the hope that it will be       //
31 // useful, but WITHOUT ANY WARRANTY; without even the    //
32 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
33 // PARTICULAR PURPOSE. See the GNU General Public        //
34 // License for more details.                             //
35 //                                                       //
36 // You should have received a copy of the GNU General    //
37 // Public License along with this program; if not, see   //
38 // <http://www.gnu.org/licenses/>.                       //
39 //                                                       //
40 //-------------------------------------------------------//
41 //                                                       //
42 //    e-mail:     wichmann@laserdata                     //
43 //                                                       //
44 //    contact:    Volker Wichmann                        //
45 //                LASERDATA GmbH                         //
46 //                Management and analysis of             //
47 //                laserscanning data                     //
48 //                Innsbruck, Austria                     //
49 //                                                       //
50 ///////////////////////////////////////////////////////////
51 
52 //---------------------------------------------------------
53 
54 
55 ///////////////////////////////////////////////////////////
56 //														 //
57 //														 //
58 //														 //
59 ///////////////////////////////////////////////////////////
60 
61 //---------------------------------------------------------
62 #include "pc_reclass_extract.h"
63 
64 
65 ///////////////////////////////////////////////////////////
66 //														 //
67 //				Construction/Destruction				 //
68 //														 //
69 ///////////////////////////////////////////////////////////
70 
71 //---------------------------------------------------------
CPC_Reclass_Extract(void)72 CPC_Reclass_Extract::CPC_Reclass_Extract(void)
73 {
74 	CSG_Parameter	*pNode;
75 
76 	//-----------------------------------------------------
77 	Set_Name(_TL("Point Cloud Reclassifier / Subset Extractor"));
78 
79 	Set_Author(SG_T("Volker Wichmann (c) 2009, LASERDATA GmbH"));
80 
81 	Set_Description	(_TW(
82 		"The tool can be used to either reclassify a Point Cloud attribute or to extract "
83 		"a subset of a Point Cloud based on the values of an attribute.\n\n"
84 		"The tool provides three different options:\n"
85 		"(a) reclassification of (or extraction based on) single values,\n"
86 		"(b) reclassification of (or extraction based on) a range of values and\n"
87 		"(c) reclassification of (or extraction based on) value ranges specified in a lookup table.\n\n"
88 		"Each of these three options provides it's own parameters. The 'new value' parameters are "
89 		"irrelevant in case a subset is extracted.\n\n"
90 		"In addition to these settings, two special cases ('NoData values' and 'other values' not "
91 		"included in the parameter setup) are supported:\n"
92 		"In mode (a) and (b) the 'NoData option' is evaluated before the method settings, in mode "
93 		"(c) the option is evaluated only if the NoData value isn't included in the lookup table.\n"
94 		"The 'other values' option is always evaluated after checking the method settings.\n\n")
95 	);
96 
97 
98 	//-----------------------------------------------------
99 	Parameters.Add_PointCloud(
100 		NULL	, "INPUT"		,_TL("Point Cloud"),
101 		_TL("Point Cloud to reclassify/extract"),
102 		PARAMETER_INPUT
103 	);
104 
105 	Parameters.Add_Table_Field(
106 		Parameters("INPUT"), "ATTRIB", _TL("Attribute"),
107 		_TL("Attribute to process."),
108 		false
109 	);
110 
111 	Parameters.Add_PointCloud(
112 		NULL	, "RESULT"		, _TL("Result"),
113 		_TL("Reclassified or extracted Point Cloud."),
114 		PARAMETER_OUTPUT
115 	);
116 
117 	Parameters.Add_Choice(
118 		NULL	, "MODE"	, _TL("Mode of operation"),
119 		_TL("Choose whether to reclassify a Point Cloud or to extract a subset from a Point Cloud."),
120 		_TL("Reclassify|Extract Subset|"), 0
121 	);
122 
123 	Parameters.Add_Value(
124 		NULL	, "CREATE_ATTRIB"	, _TL("Create new Attribute"),
125 		_TL("Check this to create a new attribute with the reclassification result. If unchecked, the existing attribute is updated."),
126 		PARAMETER_TYPE_Bool, false
127 	);
128 
129 	Parameters.Add_Choice(
130 		NULL	, "METHOD"		, _TL("Method"),
131 		_TL("Select the desired method: 1. a single value or a range defined by a single value is reclassified, 2. a range of values is reclassified, 3. the lookup table is used to reclassify the grid."),
132 		_TL("single|range|simple table|user supplied table|"), 0
133 	);
134 
135 
136 	//-----------------------------------------------------
137 	Parameters.Add_Value(
138 		NULL	, "OLD"			, _TL("old value"),
139 		_TL("Value to reclassify."),
140 		PARAMETER_TYPE_Double, 0
141 	);
142 
143 	Parameters.Add_Value(
144 		NULL	, "NEW"			, _TL("new value"),
145 		_TL("New value."),
146 		PARAMETER_TYPE_Double, 1
147 	);
148 
149 	Parameters.Add_Choice(
150 		NULL	, "SOPERATOR"	, _TL("operator"),
151 		_TL("Select the desired operator (<;.;=; >;.); it is possible to define a range above or below the old value."),
152 
153 		CSG_String::Format(SG_T("%s|%s|%s|%s|%s|"),
154 			_TL("="),
155 			_TL("<"),
156 			_TL("<="),
157 			_TL(">="),
158 			_TL(">")
159 		), 0
160 	);
161 
162 	//-----------------------------------------------------
163 	Parameters.Add_Value(
164 		NULL	, "MIN"			, _TL("minimum value"),
165 		_TL("Minimum value of the range to be reclassified."),
166 		PARAMETER_TYPE_Double, 0
167 	);
168 
169 	Parameters.Add_Value(
170 		NULL	, "MAX"			, _TL("maximum value"),
171 		_TL("Maximum value of the range to be reclassified."),
172 		PARAMETER_TYPE_Double, 10
173 	);
174 
175 	Parameters.Add_Value(
176 		NULL	, "RNEW"		, _TL("new value"),
177 		_TL("new value"),
178 		PARAMETER_TYPE_Double, 5
179 	);
180 
181 	Parameters.Add_Choice(
182 		NULL	, "ROPERATOR"	, _TL("operator"),
183 		_TL("Select operator: eg. min < value < max."),
184 
185 		CSG_String::Format(SG_T("%s|%s|"),
186 			_TL("<="),
187 			_TL("<")
188 		), 0
189 	);
190 
191 	//-----------------------------------------------------
192 	Parameters.Add_FixedTable(
193 		NULL	, "RETAB"		, _TL("Lookup Table"),
194 		_TL("Lookup table used in method \"table\"")
195 	);
196 
197 	Parameters.Add_Choice(
198 		NULL	, "TOPERATOR"	, _TL("operator"),
199 		_TL("Select the desired operator (min < value < max; min . value < max; min .value . max; min < value . max)."),
200 
201 		CSG_String::Format(SG_T("%s|%s|%s|%s|"),
202 			_TL("min <= value < max"),
203 			_TL("min <= value <= max"),
204 			_TL("min < value <= max"),
205 			_TL("min < value < max")
206 		), 0
207 	);
208 
209 	//-----------------------------------------------------
210 	pNode	= Parameters.Add_Table(
211 		NULL	, "RETAB_2"		, _TL("Lookup Table"),
212 		_TL("Lookup table used in method \"user supplied table\""),
213 		PARAMETER_INPUT_OPTIONAL
214 	);
215 
216 	Parameters.Add_Table_Field(
217 		pNode	, "F_MIN"		, _TL("minimum value"),
218 		_TL("")
219 	);
220 
221 	Parameters.Add_Table_Field(
222 		pNode	, "F_MAX"		, _TL("maximum value"),
223 		_TL("")
224 	);
225 
226 	Parameters.Add_Table_Field(
227 		pNode	, "F_CODE"		, _TL("new value"),
228 		_TL("")
229 	);
230 
231 	//-----------------------------------------------------
232 	pNode	= Parameters.Add_Node(
233 		NULL, "OPTIONS"			, _TL("Special cases"),
234 		_TL("Parameter settings for No-Data and all other values.")
235 	);
236 
237 	Parameters.Add_Value(
238 		pNode	, "NODATAOPT"	, _TL("no data values"),
239 		_TL("Use this option to reclassify No-Data values independently of the method settings."),
240 		PARAMETER_TYPE_Bool, false
241 	);
242 
243 	Parameters.Add_Value(
244 		Parameters("NODATAOPT")	, "NODATA"		, _TL("new value"),
245 		_TL("new value"),
246 		PARAMETER_TYPE_Double, 0
247 	);
248 
249 	Parameters.Add_Value(
250 		pNode	, "OTHEROPT"	, _TL("other values"),
251 		_TL("Use this option to reclassify all other values that are not specified in the options above."),
252 		PARAMETER_TYPE_Bool, false
253 	);
254 
255 	Parameters.Add_Value(
256 		Parameters("OTHEROPT")	, "OTHERS"		, _TL("new value"),
257 		_TL("new value"),
258 		PARAMETER_TYPE_Double, 0
259 	);
260 
261 	//-----------------------------------------------------
262 	CSG_Table			*pLookup;
263 	CSG_Table_Record	*pRecord;
264 
265 	pLookup	= Parameters("RETAB")->asTable();
266 
267 	pLookup->Add_Field(_TL("minimum")	, SG_DATATYPE_Double);
268 	pLookup->Add_Field(_TL("maximum")	, SG_DATATYPE_Double);
269 	pLookup->Add_Field(_TL("new")		, SG_DATATYPE_Double);
270 
271 	pRecord	= pLookup->Add_Record();	pRecord->Set_Value(0,  0.0);	pRecord->Set_Value(1, 10.0);	pRecord->Set_Value(2, 1.0);
272 	pRecord	= pLookup->Add_Record();	pRecord->Set_Value(0, 10.0);	pRecord->Set_Value(1, 20.0);	pRecord->Set_Value(2, 2.0);
273 }
274 
275 //---------------------------------------------------------
~CPC_Reclass_Extract(void)276 CPC_Reclass_Extract::~CPC_Reclass_Extract(void)
277 {}
278 
279 
280 ///////////////////////////////////////////////////////////
281 //														 //
282 //														 //
283 //														 //
284 ///////////////////////////////////////////////////////////
285 
286 //---------------------------------------------------------
On_Execute(void)287 bool CPC_Reclass_Extract::On_Execute(void)
288 {
289 	int				method;
290 	CSG_Parameters	sParms;
291 
292 	m_pInput		= Parameters("INPUT")->asPointCloud();
293 	m_pResult		= Parameters("RESULT")->asPointCloud();
294 	method			= Parameters("METHOD")->asInt();
295 	m_AttrField		= Parameters("ATTRIB")->asInt();
296 	m_bExtract		= Parameters("MODE")->asInt() == 0 ? false : true;
297 	m_bCreateAttrib	= Parameters("CREATE_ATTRIB")->asBool();
298 
299 	m_pResult->Create(m_pInput);
300 
301 	if (m_bExtract)
302 		m_pResult->Fmt_Name("%s_subset_%s", m_pInput->Get_Name(), m_pInput->Get_Field_Name(m_AttrField));
303 	else
304 	{
305 		m_pResult->Fmt_Name("%s_reclass_%s", m_pInput->Get_Name(), m_pInput->Get_Field_Name(m_AttrField));
306 		if( m_bCreateAttrib )
307 			m_pResult->Add_Field(CSG_String::Format("%s_reclass", m_pInput->Get_Field_Name(m_AttrField)), m_pInput->Get_Field_Type(m_AttrField));
308 	}
309 
310 	m_iOrig = 0;	// counter of unchanged points
311 
312 	//-----------------------------------------------------
313 	switch( method )
314 	{
315 	case 0:	Reclass_Single();		break;
316 	case 1:	Reclass_Range();		break;
317 	case 2:	if( Reclass_Table(false) )
318 				break;
319 			else
320 				return( false );
321 	case 3:	if( Reclass_Table(true) )
322 				break;
323 			else
324 				return( false );
325 	default: break;
326 	}
327 
328 	//-----------------------------------------------------
329 	DataObject_Update(m_pResult);
330 
331 	DataObject_Get_Parameters(m_pResult, sParms);
332 	if (m_bExtract)
333 		Set_Display_Attributes(m_pResult, 2, sParms);
334 	else
335 	{
336 		if( m_bCreateAttrib )
337 			Set_Display_Attributes(m_pResult, m_pResult->Get_Field_Count()-1, sParms);
338 		else
339 			Set_Display_Attributes(m_pResult, m_AttrField, sParms);
340 	}
341 
342 	if( m_bExtract)
343 		SG_UI_Msg_Add(CSG_String::Format(_TL("%d points out of %d extracted."), m_pInput->Get_Point_Count()-m_iOrig, m_pInput->Get_Point_Count()), true);
344 	else
345 		SG_UI_Msg_Add(CSG_String::Format(_TL("%d points out of %d reclassified."), m_pInput->Get_Point_Count()-m_iOrig, m_pInput->Get_Point_Count()), true);
346 
347 
348 	return( true );
349 }
350 
351 
352 ///////////////////////////////////////////////////////////
353 //														 //
354 //														 //
355 //														 //
356 ///////////////////////////////////////////////////////////
357 
358 //---------------------------------------------------------
Reclass_Range(void)359 void CPC_Reclass_Extract::Reclass_Range(void)
360 {
361 	bool		otherOpt, noDataOpt, floating;
362 	int			opera;
363 	double		minValue, maxValue, value, others, noData, noDataValue, newValue;
364 
365 	minValue	= Parameters("MIN")->asDouble();
366 	maxValue	= Parameters("MAX")->asDouble();
367 	newValue	= Parameters("RNEW")->asDouble();
368 	others		= Parameters("OTHERS")->asDouble();
369 	noData		= Parameters("NODATA")->asDouble();
370 	opera		= Parameters("ROPERATOR")->asInt();
371 
372 	otherOpt	= m_bExtract ? false : Parameters("OTHEROPT")->asBool();
373 	noDataOpt	= m_bExtract ? false : Parameters("NODATAOPT")->asBool();
374 
375 	noDataValue = m_pInput->Get_NoData_Value();
376 
377 	if( (m_pInput->Get_Field_Type(m_AttrField) == SG_DATATYPE_Double) || (m_pInput->Get_Field_Type(m_AttrField) == SG_DATATYPE_Float) )
378 		floating = true;
379 	else
380 		floating = false;
381 
382 	for (int i=0; i<m_pInput->Get_Point_Count() && Set_Progress(i, m_pInput->Get_Point_Count()); i++)
383 	{
384 		if( floating == true )
385 			value = m_pInput->Get_Value(i, m_AttrField);
386 		else
387 			value = (int)m_pInput->Get_Value(i, m_AttrField);
388 
389 		if( opera == 0 )												// operator <=
390 		{
391 			if( noDataOpt == true && value == noDataValue )				// noData option
392 				Set_Value(i, noData);
393 			else if( minValue <= value && value <= maxValue )			// reclass old range
394 				Set_Value(i, newValue);
395 			else if( otherOpt == true && value != noDataValue )			// other values option
396 				Set_Value(i, others);
397 			else
398 			{
399 				if (!m_bExtract)
400 					Set_Value(i, value);								// or original value
401 
402 				m_iOrig++;
403 			}
404 		}
405 
406 		if( opera == 1 )												// operator <
407 		{
408 			if( noDataOpt == true && value == noDataValue )				// noData option
409 				Set_Value(i, noData);
410 			else if( minValue < value && value < maxValue )				// reclass old range
411 				Set_Value(i, newValue);
412 			else if( otherOpt == true && value != noDataValue )			// other values option
413 				Set_Value(i, others);
414 			else
415 			{
416 				if (!m_bExtract)
417 					Set_Value(i, value);								// or original value
418 
419 				m_iOrig++;
420 			}
421 		}
422 	}
423 
424 	return;
425 }
426 
427 //---------------------------------------------------------
Reclass_Single(void)428 void CPC_Reclass_Extract::Reclass_Single(void)
429 {
430 	bool		otherOpt, noDataOpt, floating;
431 	int			opera;
432 	double		oldValue, newValue, value, others, noData, noDataValue;
433 
434 	oldValue	= Parameters("OLD")->asDouble();
435 	newValue	= Parameters("NEW")->asDouble();
436 	others		= Parameters("OTHERS")->asDouble();
437 	noData		= Parameters("NODATA")->asDouble();
438 	opera		= Parameters("SOPERATOR")->asInt();
439 
440 	otherOpt	= m_bExtract ? false : Parameters("OTHEROPT")->asBool();
441 	noDataOpt	= m_bExtract ? false : Parameters("NODATAOPT")->asBool();
442 
443 	noDataValue = m_pInput->Get_NoData_Value();
444 
445 	if( (m_pInput->Get_Field_Type(m_AttrField) == SG_DATATYPE_Double) || (m_pInput->Get_Field_Type(m_AttrField) == SG_DATATYPE_Float) )
446 		floating = true;
447 	else
448 		floating = false;
449 
450 
451 	for (int i=0; i<m_pInput->Get_Point_Count() && Set_Progress(i, m_pInput->Get_Point_Count()); i++)
452 	{
453 		if( floating == true )
454 			value = m_pInput->Get_Value(i, m_AttrField);
455 		else
456 			value = (int)m_pInput->Get_Value(i, m_AttrField);
457 
458 
459 		if( opera == 0 )												// operator =
460 		{
461 			if( noDataOpt == true && value == noDataValue )				// noData option
462 				Set_Value(i, noData);
463 			else if( value == oldValue )								// reclass old value
464 				Set_Value(i, newValue);
465 			else if( otherOpt == true && value != noDataValue )			// other values option
466 				Set_Value(i, others);
467 			else
468 			{
469 				if (!m_bExtract)
470 					Set_Value(i, value);								// or original value
471 
472 				m_iOrig++;
473 			}
474 		}
475 
476 		if( opera == 1 )												// operator <
477 		{
478 			if( noDataOpt == true && value == noDataValue )				// noData option
479 				Set_Value(i, noData);
480 			else if( value < oldValue )									// reclass old value
481 				Set_Value(i, newValue);
482 			else if( otherOpt == true && value != noDataValue )			// other values option
483 				Set_Value(i, others);
484 			else
485 			{
486 				if (!m_bExtract)
487 					Set_Value(i, value);								// or original value
488 
489 				m_iOrig++;
490 			}
491 		}
492 
493 		if( opera == 2 )												// operator <=
494 		{
495 			if( noDataOpt == true && value == noDataValue )				// noData option
496 				Set_Value(i, noData);
497 			else if( value <= oldValue )								// reclass old value
498 				Set_Value(i, newValue);
499 			else if( otherOpt == true && value != noDataValue )			// other values option
500 				Set_Value(i, others);
501 			else
502 			{
503 				if (!m_bExtract)
504 					Set_Value(i, value);								// or original value
505 
506 				m_iOrig++;
507 			}
508 		}
509 
510 		if( opera == 3 )												// operator >=
511 		{
512 			if( noDataOpt == true && value == noDataValue )				// noData option
513 				Set_Value(i, noData);
514 			else if( value >= oldValue )								// reclass old value
515 				Set_Value(i, newValue);
516 			else if( otherOpt == true && value != noDataValue )			// other values option
517 				Set_Value(i, others);
518 			else
519 			{
520 				if (!m_bExtract)
521 					Set_Value(i, value);								// or original value
522 
523 				m_iOrig++;
524 			}
525 		}
526 
527 		if( opera == 4 )												// operator >
528 		{
529 			if( noDataOpt == true && value == noDataValue )				// noData option
530 				Set_Value(i, noData);
531 			else if( value > oldValue )									// reclass old value
532 				Set_Value(i, newValue);
533 			else if( otherOpt == true && value != noDataValue )			// other values option
534 				Set_Value(i, others);
535 			else
536 			{
537 				if (!m_bExtract)
538 					Set_Value(i, value);								// or original value
539 
540 				m_iOrig++;
541 			}
542 		}
543 	}
544 
545 	return;
546 }
547 
548 
549 //---------------------------------------------------------
Reclass_Table(bool bUser)550 bool CPC_Reclass_Extract::Reclass_Table(bool bUser)
551 {
552 	bool				set, otherOpt, noDataOpt;
553 	int					opera, field_Min, field_Max, field_Code;
554 	double				value, others, noData, noDataValue;
555 
556 	CSG_Table			*pReTab;
557 	CSG_Table_Record	*pRecord = NULL;
558 
559 	if( bUser )
560 	{
561 		pReTab			= Parameters("RETAB_2")	->asTable();
562 		field_Min		= Parameters("F_MIN")	->asInt();
563 		field_Max		= Parameters("F_MAX")	->asInt();
564 		field_Code		= Parameters("F_CODE")	->asInt();
565 	}
566 	else
567 	{
568 		pReTab			= Parameters("RETAB")	->asTable();
569 		field_Min		= 0;
570 		field_Max		= 1;
571 		field_Code		= 2;
572 	}
573 
574 	others		= Parameters("OTHERS")->asDouble();
575 	noData		= Parameters("NODATA")->asDouble();
576 	opera		= Parameters("TOPERATOR")->asInt();
577 
578 	otherOpt	= m_bExtract ? false : Parameters("OTHEROPT")->asBool();
579 	noDataOpt	= m_bExtract ? false : Parameters("NODATAOPT")->asBool();
580 
581 	noDataValue	= m_pInput->Get_NoData_Value();
582 
583 
584 	if( pReTab == NULL )
585 	{
586 		Error_Set(_TL("You must specify a reclass table with a minimium (field 1), a maximum (field 2) and a code value (field 3)!\n"));
587 		return( false );
588 	}
589 
590 	if( pReTab->Get_Record_Count() == 0 )
591 	{
592 		Error_Set(_TL("You must specify a reclass table with a minimium of one record!\n"));
593 		return( false );
594 	}
595 
596 
597 	for (int i=0; i<m_pInput->Get_Point_Count() && Set_Progress(i, m_pInput->Get_Point_Count()); i++)
598 	{
599 		value	= m_pInput->Get_Value(i, m_AttrField);
600 		set		= false;
601 
602 		for(int iRecord=0; iRecord<pReTab->Get_Record_Count(); iRecord++)									// reclass
603 		{
604 			pRecord		= pReTab->Get_Record(iRecord);
605 
606 			if( opera == 0 )										// min <= value < max
607 			{
608 				if( value >= pRecord->asDouble(field_Min) && value < pRecord->asDouble(field_Max) )
609 				{
610 					Set_Value(i, pRecord->asDouble(field_Code));
611 					set = true;
612 					break;
613 				}
614 			}
615 			else if( opera == 1 )									// min <= value <= max
616 			{
617 				if( value >= pRecord->asDouble(field_Min) && value <= pRecord->asDouble(field_Max) )
618 				{
619 					Set_Value(i, pRecord->asDouble(field_Code));
620 					set = true;
621 					break;
622 				}
623 			}
624 			else if( opera == 2 )									// min < value <= max
625 			{
626 				if( value > pRecord->asDouble(field_Min) && value <= pRecord->asDouble(field_Max) )
627 				{
628 					Set_Value(i, pRecord->asDouble(field_Code));
629 					set = true;
630 					break;
631 				}
632 			}
633 			else if( opera == 3 )									// min < value < max
634 			{
635 				if( value > pRecord->asDouble(field_Min) && value < pRecord->asDouble(field_Max) )
636 				{
637 					Set_Value(i, pRecord->asDouble(field_Code));
638 					set = true;
639 					break;
640 				}
641 			}
642 		}
643 
644 		if( set == false )
645 		{
646 			if( noDataOpt == true && value == noDataValue )			// noData option
647 				Set_Value(i, noData);
648 			else if( otherOpt == true && value != noDataValue)		// other values option
649 				Set_Value(i, others);
650 			else
651 			{
652 				if (!m_bExtract)
653 					Set_Value(i, value);							// or original value
654 
655 				m_iOrig++;
656 			}
657 		}
658 	}
659 
660 	return (true);
661 }
662 
663 
664 //---------------------------------------------------------
Set_Value(int i,double value)665 void CPC_Reclass_Extract::Set_Value(int i, double value)
666 {
667 	m_pResult->Add_Point(m_pInput->Get_X(i), m_pInput->Get_Y(i), m_pInput->Get_Z(i));
668 
669 	for (int j=0; j<m_pInput->Get_Attribute_Count(); j++)
670 	{
671 		switch (m_pInput->Get_Attribute_Type(j))
672 		{
673 		default:					m_pResult->Set_Attribute(j, m_pInput->Get_Attribute(i, j));		break;
674 		case SG_DATATYPE_Date:
675 		case SG_DATATYPE_String:	CSG_String sAttr; m_pInput->Get_Attribute(i, j, sAttr); m_pResult->Set_Attribute(j, sAttr);		break;
676 		}
677 	}
678 
679 	if (!m_bExtract)
680 	{
681 		if (m_bCreateAttrib)
682 			m_pResult->Set_Value(m_pResult->Get_Field_Count()-1, value);
683 		else
684 			m_pResult->Set_Value(m_AttrField, value);
685 	}
686 
687 	return;
688 }
689 
690 
691 //---------------------------------------------------------
Set_Display_Attributes(CSG_PointCloud * pPC,int iField,CSG_Parameters & sParms)692 void CPC_Reclass_Extract::Set_Display_Attributes(CSG_PointCloud *pPC, int iField, CSG_Parameters &sParms)
693 {
694 	if (sParms("METRIC_ATTRIB")	&& sParms("COLORS_TYPE") && sParms("METRIC_COLORS")
695 		&& sParms("METRIC_ZRANGE") && sParms("DISPLAY_VALUE_AGGREGATE"))
696 	{
697 		sParms("DISPLAY_VALUE_AGGREGATE")->Set_Value(3);		// highest z
698 		sParms("COLORS_TYPE")->Set_Value(2);                    // graduated color
699 		sParms("METRIC_COLORS")->asColors()->Set_Count(255);    // number of colors
700 		sParms("METRIC_ATTRIB")->Set_Value(iField);				// attrib
701 		sParms("METRIC_ZRANGE")->asRange()->Set_Range(pPC->Get_Minimum(iField), pPC->Get_Maximum(iField));
702 	}
703 
704 	DataObject_Set_Parameters(pPC, sParms);
705 	DataObject_Update(pPC);
706 
707 	return;
708 }
709 
710 
711 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)712 int CPC_Reclass_Extract::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
713 {
714 	if(	pParameter->Cmp_Identifier(SG_T("METHOD")) || pParameter->Cmp_Identifier(SG_T("MODE")) )
715 	{
716 		int		iMode	= pParameters->Get_Parameter("MODE")->asInt();		// 0 == reclassify, 1 == extract
717 		int		Value	= pParameters->Get_Parameter("METHOD")->asInt();
718 
719 		pParameters->Get_Parameter("CREATE_ATTRIB")->Set_Enabled(iMode == 0);
720 
721 		// single
722 		pParameters->Get_Parameter("OLD"		)->Set_Enabled(Value == 0);
723 		pParameters->Get_Parameter("NEW"		)->Set_Enabled(Value == 0 && iMode == 0);
724 		pParameters->Get_Parameter("SOPERATOR"	)->Set_Enabled(Value == 0);
725 
726 		// range
727 		pParameters->Get_Parameter("MIN"		)->Set_Enabled(Value == 1);
728 		pParameters->Get_Parameter("MAX"		)->Set_Enabled(Value == 1);
729 		pParameters->Get_Parameter("RNEW"		)->Set_Enabled(Value == 1 && iMode == 0);
730 		pParameters->Get_Parameter("ROPERATOR"	)->Set_Enabled(Value == 1);
731 
732 		// simple table
733 		pParameters->Get_Parameter("RETAB"		)->Set_Enabled(Value == 2);
734 
735 		// user supplied table
736 		pParameters->Get_Parameter("RETAB_2"	)->Set_Enabled(Value == 3);
737 
738 		// lookup table
739 		pParameters->Get_Parameter("TOPERATOR"	)->Set_Enabled(Value >= 2);
740 
741 		// other options
742 		pParameters->Get_Parameter("NODATAOPT"	)->Set_Enabled(iMode == 0);
743 		pParameters->Get_Parameter("OTHEROPT"	)->Set_Enabled(iMode == 0);
744 	}
745 
746 	if(	pParameter->Cmp_Identifier(SG_T("NODATAOPT")) )
747 	{
748 		pParameters->Get_Parameter("NODATA"		)->Set_Enabled(pParameter->asInt() > 0);
749 	}
750 
751 	if(	pParameter->Cmp_Identifier(SG_T("OTHEROPT")) )
752 	{
753 		pParameters->Get_Parameter("OTHERS"		)->Set_Enabled(pParameter->asInt() > 0);
754 	}
755 
756 	//-----------------------------------------------------
757 	return (1);
758 }
759 
760 
761 ///////////////////////////////////////////////////////////
762 //														 //
763 //														 //
764 //														 //
765 ///////////////////////////////////////////////////////////
766 
767 //---------------------------------------------------------
768