1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //           Application Programming Interface           //
9 //                                                       //
10 //                  Library: SAGA_API                    //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                    dataobject.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'.                              //
22 //                                                       //
23 // This library is free software; you can redistribute   //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free       //
26 // Software Foundation, either version 2.1 of the        //
27 // License, or (at your option) any later version.       //
28 //                                                       //
29 // This library is distributed in the hope that it will  //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details.                             //
34 //                                                       //
35 // You should have received a copy of the GNU Lesser     //
36 // General Public License along with this program; if    //
37 // not, see <http://www.gnu.org/licenses/>.              //
38 //                                                       //
39 //-------------------------------------------------------//
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Goettingen               //
44 //                Goldschmidtstr. 5                      //
45 //                37077 Goettingen                       //
46 //                Germany                                //
47 //                                                       //
48 //    e-mail:     oconrad@saga-gis.org                   //
49 //                                                       //
50 ///////////////////////////////////////////////////////////
51 
52 //---------------------------------------------------------
53 
54 
55 ///////////////////////////////////////////////////////////
56 //														 //
57 //					class CData_Object					 //
58 //														 //
59 ///////////////////////////////////////////////////////////
60 
61 //---------------------------------------------------------
62 #include "dataobject.h"
63 
64 #include <wx/string.h>
65 
66 
67 ///////////////////////////////////////////////////////////
68 //														 //
69 //														 //
70 //														 //
71 ///////////////////////////////////////////////////////////
72 
73 //---------------------------------------------------------
SG_Get_Create_Pointer(void)74 void *		SG_Get_Create_Pointer(void)
75 {
76 	return( DATAOBJECT_CREATE );
77 }
78 
79 //---------------------------------------------------------
SG_Get_DataObject_Identifier(TSG_Data_Object_Type Type)80 CSG_String	SG_Get_DataObject_Identifier(TSG_Data_Object_Type Type)
81 {
82 	switch( Type )
83 	{
84 	default                           : return( "UNDEFINED" );
85 	case SG_DATAOBJECT_TYPE_Grid      : return( "GRID"      );
86 	case SG_DATAOBJECT_TYPE_Grids     : return( "GRIDS"     );
87 	case SG_DATAOBJECT_TYPE_Table     : return( "TABLE"     );
88 	case SG_DATAOBJECT_TYPE_Shapes    : return( "SHAPES"    );
89 	case SG_DATAOBJECT_TYPE_TIN       : return( "TIN"       );
90 	case SG_DATAOBJECT_TYPE_PointCloud: return( "POINTS"    );
91 	}
92 }
93 
94 //---------------------------------------------------------
SG_Get_DataObject_Name(TSG_Data_Object_Type Type)95 CSG_String	SG_Get_DataObject_Name(TSG_Data_Object_Type Type)
96 {
97 	switch( Type )
98 	{
99 	default                           : return( _TL("Undefined"  ) );
100 	case SG_DATAOBJECT_TYPE_Grid      : return( _TL("Grid"       ) );
101 	case SG_DATAOBJECT_TYPE_Grids     : return( _TL("Grids"      ) );
102 	case SG_DATAOBJECT_TYPE_Table     : return( _TL("Table"      ) );
103 	case SG_DATAOBJECT_TYPE_Shapes    : return( _TL("Shapes"     ) );
104 	case SG_DATAOBJECT_TYPE_TIN       : return( _TL("TIN"        ) );
105 	case SG_DATAOBJECT_TYPE_PointCloud: return( _TL("Point Cloud") );
106 	}
107 }
108 
109 
110 ///////////////////////////////////////////////////////////
111 //														 //
112 //				Data Object Statistics					 //
113 //														 //
114 ///////////////////////////////////////////////////////////
115 
116 //---------------------------------------------------------
117 static sLong		gSG_DataObject_Max_Samples	= 0;
118 
119 //---------------------------------------------------------
SG_DataObject_Set_Max_Samples(sLong Max_Samples)120 bool				SG_DataObject_Set_Max_Samples	(sLong Max_Samples)
121 {
122 	if( Max_Samples >= 0 )
123 	{
124 		gSG_DataObject_Max_Samples	= Max_Samples;
125 
126 		return( true );
127 	}
128 
129 	return( false );
130 }
131 
132 //---------------------------------------------------------
SG_DataObject_Get_Max_Samples(void)133 sLong				SG_DataObject_Get_Max_Samples	(void)
134 {
135 	return( gSG_DataObject_Max_Samples );
136 }
137 
138 
139 ///////////////////////////////////////////////////////////
140 //														 //
141 //														 //
142 //														 //
143 ///////////////////////////////////////////////////////////
144 
145 //---------------------------------------------------------
146 int		g_History_Depth	= -1;
147 
SG_Set_History_Depth(int Depth)148 void	SG_Set_History_Depth			(int Depth)
149 {
150 	g_History_Depth	= Depth;
151 }
152 
SG_Get_History_Depth(void)153 int		SG_Get_History_Depth			(void)
154 {
155 	return( g_History_Depth );
156 }
157 
158 //---------------------------------------------------------
159 int		g_History_Ignore_Lists	= true;
160 
SG_Set_History_Ignore_Lists(int Ignore)161 void	SG_Set_History_Ignore_Lists		(int Ignore)
162 {
163 	g_History_Ignore_Lists	= Ignore != 0;
164 }
165 
SG_Get_History_Ignore_Lists(void)166 int		SG_Get_History_Ignore_Lists		(void)
167 {
168 	return( g_History_Ignore_Lists );
169 }
170 
171 
172 ///////////////////////////////////////////////////////////
173 //														 //
174 //														 //
175 //														 //
176 ///////////////////////////////////////////////////////////
177 
178 //---------------------------------------------------------
CSG_Data_Object(void)179 CSG_Data_Object::CSG_Data_Object(void)
180 {
181 	m_MetaData.Set_Name("SAGA_METADATA");
182 
183 	m_pMD_Database		= m_MetaData.Add_Child(SG_META_DATABASE);
184 	m_pMD_Source		= m_MetaData.Add_Child(SG_META_SOURCE  );
185 	m_pMD_History		= m_MetaData.Add_Child(SG_META_HISTORY );
186 
187 	//-----------------------------------------------------
188 	m_File_bNative		= false;
189 	m_File_Type			= 0;
190 	m_bModified			= true;
191 
192 	m_NoData_Value[0]	= -99999.;
193 	m_NoData_Value[1]	= -99999.;
194 
195 	m_Max_Samples		= gSG_DataObject_Max_Samples;
196 
197 	m_Name				.Clear();
198 	m_Description		.Clear();
199 
200 	m_bUpdate			= false;
201 
202 	m_pOwner			= NULL;
203 }
204 
205 //---------------------------------------------------------
~CSG_Data_Object(void)206 CSG_Data_Object::~CSG_Data_Object(void)
207 {
208 	Destroy();
209 }
210 
211 //---------------------------------------------------------
Destroy(void)212 bool CSG_Data_Object::Destroy(void)
213 {
214 	m_Name.Clear(); m_Description.Clear();
215 
216 	m_pMD_Database->Destroy();
217 	m_pMD_Source  ->Destroy();
218 	m_pMD_History ->Destroy();
219 
220 	return( true );
221 }
222 
223 
224 ///////////////////////////////////////////////////////////
225 //														 //
226 ///////////////////////////////////////////////////////////
227 
228 //---------------------------------------------------------
Set_Name(const CSG_String & Name)229 void CSG_Data_Object::Set_Name(const CSG_String &Name)
230 {
231 	if( Name.is_Empty() )
232 	{
233 		m_Name	= _TL("Data");
234 	}
235 	else
236 	{
237 		m_Name	= Name;
238 	}
239 }
240 
241 //---------------------------------------------------------
Fmt_Name(const char * Format,...)242 void CSG_Data_Object::Fmt_Name(const char *Format, ...)
243 {
244 	wxString	_s;
245 
246 	va_list	argptr;
247 
248 #ifdef _SAGA_LINUX
249 	wxString _Format(Format); _Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
250 	va_start(argptr, _Format); _s.PrintfV(_Format, argptr);
251 #else
252 	va_start(argptr,  Format); _s.PrintfV( Format, argptr);
253 #endif
254 
255 	va_end(argptr);
256 
257 	Set_Name(CSG_String(&_s));
258 }
259 
260 //---------------------------------------------------------
Fmt_Name(const wchar_t * Format,...)261 void CSG_Data_Object::Fmt_Name(const wchar_t *Format, ...)
262 {
263 	wxString	_s;
264 
265 	va_list	argptr;
266 
267 #ifdef _SAGA_LINUX
268 	// workaround as we only use wide characters
269 	// since wx 2.9.4 so interpret strings as multibyte
270 	wxString _Format(Format); _Format.Replace("%s", "%ls");	// workaround as we only use wide characters since wx 2.9.4 so interpret strings as multibyte
271 	va_start(argptr, _Format); _s.PrintfV(_Format, argptr);
272 #else
273 	va_start(argptr,  Format); _s.PrintfV( Format, argptr);
274 #endif
275 
276 	va_end(argptr);
277 
278 	CSG_String	s(&_s);
279 
280 	Set_Name(CSG_String(&_s));
281 }
282 
283 //---------------------------------------------------------
Get_Name(void) const284 const SG_Char * CSG_Data_Object::Get_Name(void) const
285 {
286 	return( m_Name );
287 }
288 
289 //---------------------------------------------------------
Set_Description(const CSG_String & Description)290 void CSG_Data_Object::Set_Description(const CSG_String &Description)
291 {
292 	m_Description	= Description;
293 }
294 
Get_Description(void) const295 const SG_Char * CSG_Data_Object::Get_Description(void) const
296 {
297 	return( m_pOwner ? m_pOwner->m_Description : m_Description );
298 }
299 
300 //---------------------------------------------------------
Set_File_Name(const CSG_String & FileName)301 void CSG_Data_Object::Set_File_Name	(const CSG_String &FileName)
302 {
303 	Set_File_Name(FileName, false);
304 }
305 
306 //---------------------------------------------------------
Set_File_Name(const CSG_String & FileName,bool bNative)307 void CSG_Data_Object::Set_File_Name(const CSG_String &FileName, bool bNative)
308 {
309 	m_FileName		= FileName;
310 	m_File_bNative	= bNative;
311 
312 	m_Name			= SG_File_Get_Name(FileName, false);
313 
314 	m_bModified		= false;
315 }
316 
317 //---------------------------------------------------------
Get_File_Name(bool bNative) const318 const SG_Char * CSG_Data_Object::Get_File_Name(bool bNative)	const
319 {
320 	if( bNative && !m_File_bNative )
321 	{
322 		return( SG_T("") );
323 	}
324 
325 	if( m_pOwner )
326 	{
327 		if( m_pOwner->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grids )
328 		{
329 			return( m_pOwner->m_FileName.c_str() );
330 		}
331 	}
332 
333 	return( m_FileName.c_str() );
334 }
335 
336 //---------------------------------------------------------
Get_File_Type(void) const337 int CSG_Data_Object::Get_File_Type(void)	const
338 {
339 	return( m_File_Type );
340 }
341 
342 
343 ///////////////////////////////////////////////////////////
344 //														 //
345 ///////////////////////////////////////////////////////////
346 
347 //---------------------------------------------------------
Reload(void)348 bool CSG_Data_Object::Reload(void)
349 {
350 	return( m_File_bNative && SG_File_Exists(m_FileName) && On_Reload() );
351 }
352 
353 //---------------------------------------------------------
Delete(void)354 bool CSG_Data_Object::Delete(void)
355 {
356 	if( m_File_bNative && SG_File_Exists(m_FileName) && On_Delete() )
357 	{
358 		CSG_String	FileName	= m_FileName;
359 
360 		switch( Get_ObjectType() )
361 		{
362 		case SG_DATAOBJECT_TYPE_Grid      : SG_File_Set_Extension(FileName, "mgrd"   ); break;
363 		case SG_DATAOBJECT_TYPE_Grids     : SG_File_Set_Extension(FileName, "sg-info"); break;
364 		case SG_DATAOBJECT_TYPE_Table     : SG_File_Set_Extension(FileName, "mtab"   ); break;
365 		case SG_DATAOBJECT_TYPE_Shapes    : SG_File_Set_Extension(FileName, "mshp"   ); break;
366 		case SG_DATAOBJECT_TYPE_TIN       : SG_File_Set_Extension(FileName, "sg-info"); break;
367 		case SG_DATAOBJECT_TYPE_PointCloud: SG_File_Set_Extension(FileName, "sg-info"); break;
368 		default                           : SG_File_Set_Extension(FileName, "sg-info"); break;
369 		}
370 
371 		SG_File_Delete(FileName);
372 
373 		SG_File_Set_Extension(FileName,    "prj"); SG_File_Delete(FileName);
374 		SG_File_Set_Extension(FileName, "sg-prj"); SG_File_Delete(FileName);
375 
376 		//-------------------------------------------------
377 		m_FileName		= "";
378 		m_File_bNative	= false;
379 		m_File_Type		= 0;
380 
381 		m_bModified		= true;
382 
383 		m_pMD_Database->Destroy();
384 
385 		return( true );
386 	}
387 
388 	return( false );
389 }
390 
391 
392 ///////////////////////////////////////////////////////////
393 //														 //
394 ///////////////////////////////////////////////////////////
395 
396 //---------------------------------------------------------
Set_NoData_Value(double Value)397 bool CSG_Data_Object::Set_NoData_Value(double Value)
398 {
399 	return( Set_NoData_Value_Range(Value, Value) );
400 }
401 
402 //---------------------------------------------------------
Set_NoData_Value_Range(double Lower,double Upper)403 bool CSG_Data_Object::Set_NoData_Value_Range(double Lower, double Upper)
404 {
405 	if( Lower > Upper )
406 	{
407 		double d = Lower; Lower = Upper; Upper = d;
408 	}
409 
410 	if( Lower != m_NoData_Value[0] || Upper != m_NoData_Value[1] )
411 	{
412 		m_NoData_Value[0]	= Lower;
413 		m_NoData_Value[1]	= Upper;
414 
415 		Set_Modified();
416 
417 		On_NoData_Changed();
418 
419 		return( true );
420 	}
421 
422 	return( false );
423 }
424 
425 //---------------------------------------------------------
On_NoData_Changed(void)426 bool CSG_Data_Object::On_NoData_Changed(void)
427 {
428 	if( !Get_Update_Flag() )
429 	{
430 		Set_Update_Flag();
431 	}
432 
433 	return( true );
434 }
435 
436 
437 ///////////////////////////////////////////////////////////
438 //														 //
439 ///////////////////////////////////////////////////////////
440 
441 //---------------------------------------------------------
Set_Max_Samples(sLong Max_Samples)442 bool CSG_Data_Object::Set_Max_Samples(sLong Max_Samples)
443 {
444 	#define	Min_Samples	100
445 
446 	if( m_Max_Samples != Max_Samples && Max_Samples >= Min_Samples )
447 	{
448 		m_Max_Samples	= Max_Samples;
449 
450         On_Update();
451 	}
452 
453 	return( true );
454 }
455 
456 
457 ///////////////////////////////////////////////////////////
458 //														 //
459 ///////////////////////////////////////////////////////////
460 
461 //---------------------------------------------------------
Get_Projection(void)462 CSG_Projection & CSG_Data_Object::Get_Projection(void)
463 {
464 	return( m_pOwner ? m_pOwner->m_Projection : m_Projection );
465 }
466 
467 //---------------------------------------------------------
Get_Projection(void) const468 const CSG_Projection & CSG_Data_Object::Get_Projection(void) const
469 {
470 	return( m_pOwner ? m_pOwner->m_Projection : m_Projection );
471 }
472 
473 
474 ///////////////////////////////////////////////////////////
475 //														 //
476 ///////////////////////////////////////////////////////////
477 
478 //---------------------------------------------------------
Load_MetaData(const CSG_String & _FileName)479 bool CSG_Data_Object::Load_MetaData(const CSG_String &_FileName)
480 {
481 	CSG_String	FileName(_FileName);
482 
483 	switch( Get_ObjectType() )
484 	{
485 	case SG_DATAOBJECT_TYPE_Grid      : SG_File_Set_Extension(FileName, "mgrd"   ); break;
486 	case SG_DATAOBJECT_TYPE_Grids     : SG_File_Set_Extension(FileName, "sg-info"); break;
487 	case SG_DATAOBJECT_TYPE_Table     : SG_File_Set_Extension(FileName, "mtab"   ); break;
488 	case SG_DATAOBJECT_TYPE_Shapes    : SG_File_Set_Extension(FileName, "mshp"   ); break;
489 	case SG_DATAOBJECT_TYPE_TIN       : SG_File_Set_Extension(FileName, "sg-info"); break;
490 	case SG_DATAOBJECT_TYPE_PointCloud: SG_File_Set_Extension(FileName, "sg-info");
491 		if( !SG_File_Get_Extension(_FileName).CmpNoCase("spc") ) SG_File_Set_Extension(FileName, "mpts"); break;
492 
493 	default:	return( false );
494 	}
495 
496 	CSG_File	Stream(FileName, SG_FILE_R, false);
497 
498 	return( Load_MetaData(Stream) );
499 }
500 
501 //---------------------------------------------------------
Save_MetaData(const CSG_String & _FileName)502 bool CSG_Data_Object::Save_MetaData(const CSG_String &_FileName)
503 {
504 	CSG_String	FileName(_FileName);
505 
506 	switch( Get_ObjectType() )
507 	{
508 	case SG_DATAOBJECT_TYPE_Grid      : SG_File_Set_Extension(FileName, "mgrd"   ); break;
509 	case SG_DATAOBJECT_TYPE_Grids     : SG_File_Set_Extension(FileName, "sg-info"); break;
510 	case SG_DATAOBJECT_TYPE_Table     : SG_File_Set_Extension(FileName, "mtab"   ); break;
511 	case SG_DATAOBJECT_TYPE_Shapes    : SG_File_Set_Extension(FileName, "mshp"   ); break;
512 	case SG_DATAOBJECT_TYPE_TIN       : SG_File_Set_Extension(FileName, "sg-info"); break;
513 	case SG_DATAOBJECT_TYPE_PointCloud: SG_File_Set_Extension(FileName, "sg-info"); break;
514 
515 	default:	return( false );
516 	}
517 
518 	CSG_File	Stream(FileName, SG_FILE_W, false);
519 
520 	return( Save_MetaData(Stream) );
521 }
522 
523 //---------------------------------------------------------
Load_MetaData(CSG_File & Stream)524 bool CSG_Data_Object::Load_MetaData(CSG_File &Stream)
525 {
526 	CSG_MetaData	m;
527 
528 	if( !m.Load(Stream) )
529 	{
530 		return( false );
531 	}
532 
533 	//-----------------------------------------------------
534 	if( m("DESCRIPTION") && !m["DESCRIPTION"].Get_Content().is_Empty() )
535 	{
536 		Set_Description(m["DESCRIPTION"].Get_Content());
537 	}
538 
539 	//-----------------------------------------------------
540 	m_pMD_Source->Destroy();
541 
542 	if( m(SG_META_SOURCE) )
543 		m_pMD_Source->Assign(m[SG_META_SOURCE]);
544 
545 	//-----------------------------------------------------
546 	m_pMD_Database->Destroy();
547 
548 	if( m(SG_META_DATABASE) )
549 		m_pMD_Database->Assign(m[SG_META_DATABASE]);
550 
551 	//-----------------------------------------------------
552 	m_MetaData.Del_Child(SG_META_PROJECTION);
553 
554 	if( m(SG_META_PROJECTION) && m_Projection.Load(m[SG_META_PROJECTION]) )
555 		m_MetaData.Add_Child(m[SG_META_PROJECTION]);
556 	else if( m[SG_META_SOURCE](SG_META_PROJECTION) && m_Projection.Load(m[SG_META_SOURCE][SG_META_PROJECTION]) )
557 		m_MetaData.Add_Child(m[SG_META_SOURCE][SG_META_PROJECTION]);
558 
559 	//-----------------------------------------------------
560 	m_pMD_History->Destroy();
561 
562 	if( m(SG_META_HISTORY) )
563 		m_pMD_History->Assign(m[SG_META_HISTORY]);
564 	else
565 		m_pMD_History->Add_Child(SG_META_FILEPATH, Get_File_Name());
566 
567 	return( true );
568 }
569 
570 //---------------------------------------------------------
Save_MetaData(CSG_File & Stream)571 bool CSG_Data_Object::Save_MetaData(CSG_File &Stream)
572 {
573 	//-----------------------------------------------------
574 	if( m_MetaData(SG_META_FILEPATH) )
575 		m_MetaData(SG_META_FILEPATH)->Set_Content(m_FileName);
576 	else
577 		m_MetaData.Add_Child(SG_META_FILEPATH, m_FileName);
578 
579 	//-----------------------------------------------------
580 	if( m_MetaData("DESCRIPTION") )
581 		m_MetaData("DESCRIPTION")->Set_Content(Get_Description());
582 	else
583 		m_MetaData.Add_Child("DESCRIPTION", Get_Description());
584 
585 	//-----------------------------------------------------
586 	if( m_Projection.Get_Type() == SG_PROJ_TYPE_CS_Undefined )
587 		m_MetaData.Del_Child(SG_META_PROJECTION);
588 	else if( m_MetaData(SG_META_PROJECTION) )
589 		m_Projection.Save(*m_MetaData(SG_META_PROJECTION));
590 	else
591 		m_Projection.Save(*m_MetaData.Add_Child(SG_META_PROJECTION));
592 
593 	//-----------------------------------------------------
594 	return( m_MetaData.Save(Stream) );
595 }
596 
597 //---------------------------------------------------------
Update(bool bForce)598 bool CSG_Data_Object::Update(bool bForce)
599 {
600 	if( m_bUpdate || bForce )
601 	{
602 		m_bUpdate	= false;
603 
604 		return( On_Update() );
605 	}
606 
607 	return( true );
608 }
609 
610 
611 ///////////////////////////////////////////////////////////
612 //														 //
613 ///////////////////////////////////////////////////////////
614 
615 //---------------------------------------------------------
Assign(CSG_Data_Object * pObject)616 bool CSG_Data_Object::Assign(CSG_Data_Object *pObject)
617 {
618 	return( false );
619 }
620 
621 
622 ///////////////////////////////////////////////////////////
623 //														 //
624 ///////////////////////////////////////////////////////////
625 
626 //---------------------------------------------------------
627 #include "tool_chain.h"
628 
629 //---------------------------------------------------------
Save_History_to_Model(const CSG_String & File) const630 bool CSG_Data_Object::Save_History_to_Model(const CSG_String &File)	const
631 {
632 	return( CSG_Tool_Chain::Save_History_to_Model(Get_History(), File) );
633 }
634 
635 
636 ///////////////////////////////////////////////////////////
637 //														 //
638 //														 //
639 //														 //
640 ///////////////////////////////////////////////////////////
641 
642 //---------------------------------------------------------
643