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 //                      grids.cpp                        //
15 //                                                       //
16 //                 Copyright (C) 2017 by                 //
17 //                      Olaf Conrad                      //
18 //                                                       //
19 //-------------------------------------------------------//
20 //                                                       //
21 // This file is part of 'SAGA - System for Automated     //
22 // Geoscientific Analyses'.                              //
23 //                                                       //
24 // This library is free software; you can redistribute   //
25 // it and/or modify it under the terms of the GNU Lesser //
26 // General Public License as published by the Free       //
27 // Software Foundation, either version 2.1 of the        //
28 // License, or (at your option) any later version.       //
29 //                                                       //
30 // This library is distributed in the hope that it will  //
31 // be useful, but WITHOUT ANY WARRANTY; without even the //
32 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
33 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
34 // License for more details.                             //
35 //                                                       //
36 // You should have received a copy of the GNU Lesser     //
37 // General Public License along with this program; if    //
38 // not, see <http://www.gnu.org/licenses/>.              //
39 //                                                       //
40 //-------------------------------------------------------//
41 //                                                       //
42 //    e-mail:     oconrad@saga-gis.org                   //
43 //                                                       //
44 //    contact:    Olaf Conrad                            //
45 //                Institute of Geography                 //
46 //                University of Hamburg                  //
47 //                Germany                                //
48 //                                                       //
49 ///////////////////////////////////////////////////////////
50 
51 //---------------------------------------------------------
52 #include "saga_api.h"
53 #include "grids.h"
54 #include "data_manager.h"
55 #include "tool_library.h"
56 
57 
58 ///////////////////////////////////////////////////////////
59 //														 //
60 //														 //
61 //														 //
62 ///////////////////////////////////////////////////////////
63 
64 //---------------------------------------------------------
SG_Create_Grids(void)65 CSG_Grids * SG_Create_Grids(void)
66 {
67 	return( new CSG_Grids );
68 }
69 
70 //---------------------------------------------------------
SG_Create_Grids(const CSG_Grids & Grids)71 CSG_Grids * SG_Create_Grids(const CSG_Grids &Grids)
72 {
73 	CSG_Grids	*pGrids	= new CSG_Grids(Grids);
74 
75 	if( !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
76 }
77 
78 //---------------------------------------------------------
SG_Create_Grids(const CSG_Grids * _pGrids,bool bCopyData)79 CSG_Grids * SG_Create_Grids(const CSG_Grids *_pGrids, bool bCopyData)
80 {
81 	CSG_Grids	*pGrids	= new CSG_Grids(_pGrids, bCopyData);
82 
83 	if( !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
84 }
85 
86 //---------------------------------------------------------
SG_Create_Grids(const CSG_String & FileName,bool bLoadData)87 CSG_Grids * SG_Create_Grids(const CSG_String &FileName, bool bLoadData)
88 {
89 	CSG_Grids	*pGrids	= new CSG_Grids(FileName, bLoadData);
90 
91 	if( !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
92 }
93 
94 //---------------------------------------------------------
SG_Create_Grids(const CSG_Grid_System & System,int NZ,double zMin,TSG_Data_Type Type)95 CSG_Grids * SG_Create_Grids(const CSG_Grid_System &System, int NZ, double zMin, TSG_Data_Type Type)
96 {
97 	CSG_Grids	*pGrids	= new CSG_Grids(System, NZ, zMin, Type);
98 
99 	if( !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
100 }
101 
102 //---------------------------------------------------------
SG_Create_Grids(const CSG_Grid_System & System,const CSG_Table & Attributes,int zAttribute,TSG_Data_Type Type,bool bCreateGrids)103 CSG_Grids * SG_Create_Grids(const CSG_Grid_System &System, const CSG_Table &Attributes, int zAttribute, TSG_Data_Type Type, bool bCreateGrids)
104 {
105 	CSG_Grids	*pGrids	= new CSG_Grids(System, Attributes, zAttribute, Type, bCreateGrids);
106 
107 	if( bCreateGrids && !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
108 }
109 
110 //---------------------------------------------------------
SG_Create_Grids(int NX,int NY,int NZ,double Cellsize,double xMin,double yMin,double zMin,TSG_Data_Type Type)111 CSG_Grids * SG_Create_Grids(int NX, int NY, int NZ, double Cellsize, double xMin, double yMin, double zMin, TSG_Data_Type Type)
112 {
113 	CSG_Grids	*pGrids	= new CSG_Grids(NX, NY, NZ, Cellsize, xMin, yMin, zMin, Type);
114 
115 	if( !pGrids->is_Valid() ) { delete(pGrids); pGrids = NULL; } return( pGrids );
116 }
117 
118 
119 ///////////////////////////////////////////////////////////
120 //														 //
121 //														 //
122 //														 //
123 ///////////////////////////////////////////////////////////
124 
125 //---------------------------------------------------------
126 /**
127   * Default constructor.
128 */
129 //---------------------------------------------------------
CSG_Grids(void)130 CSG_Grids::CSG_Grids(void)
131 {
132 	_On_Construction();
133 }
134 
135 //---------------------------------------------------------
136 /**
137   * The destructor.
138 */
~CSG_Grids(void)139 CSG_Grids::~CSG_Grids(void)
140 {
141 	Destroy();
142 
143 	delete(m_pGrids[0]);	// The Dummy
144 }
145 
146 //---------------------------------------------------------
147 /**
148   * Copy constructor.
149 */
150 //---------------------------------------------------------
CSG_Grids(const CSG_Grids & Grids)151 CSG_Grids::CSG_Grids(const CSG_Grids &Grids)
152 {
153 	_On_Construction();
154 
155 	Create(Grids);
156 }
157 
158 //---------------------------------------------------------
159 /**
160   * Create a grid collection using the pGrids's grid system,
161   * data type, and attribute field definition. If bCopyData
162   * is true, it also copies the data. Otherwise it has no
163   * initial data.
164 */
165 //---------------------------------------------------------
CSG_Grids(const CSG_Grids * pGrids,bool bCopyData)166 CSG_Grids::CSG_Grids(const CSG_Grids *pGrids, bool bCopyData)
167 {
168 	_On_Construction();
169 
170 	Create(pGrids, bCopyData);
171 }
172 
173 //---------------------------------------------------------
174 /**
175   * Create a grid collection from file.
176 */
177 //---------------------------------------------------------
CSG_Grids(const CSG_String & FileName,bool bLoadData)178 CSG_Grids::CSG_Grids(const CSG_String &FileName, bool bLoadData)
179 {
180 	_On_Construction();
181 
182 	Create(FileName, bLoadData);
183 }
184 
185 //---------------------------------------------------------
186 /**
187   * Create a grid collection with specified dimensions'.
188 */
189 //---------------------------------------------------------
CSG_Grids(int NX,int NY,int NZ,double Cellsize,double xMin,double yMin,double zMin,TSG_Data_Type Type)190 CSG_Grids::CSG_Grids(int NX, int NY, int NZ, double Cellsize, double xMin, double yMin, double zMin, TSG_Data_Type Type)
191 {
192 	_On_Construction();
193 
194 	Create(NX, NY, NZ, Cellsize, xMin, yMin, zMin, Type);
195 }
196 
197 //---------------------------------------------------------
198 /**
199   * Create a grid collection with specified dimensions'.
200 */
201 //---------------------------------------------------------
CSG_Grids(const CSG_Grid_System & System,int NZ,double zMin,TSG_Data_Type Type)202 CSG_Grids::CSG_Grids(const CSG_Grid_System &System, int NZ, double zMin, TSG_Data_Type Type)
203 {
204 	_On_Construction();
205 
206 	Create(System, NZ, zMin, Type);
207 }
208 
209 //---------------------------------------------------------
210 /**
211   * Create a grid collection with specified dimensions'.
212 */
213 //---------------------------------------------------------
CSG_Grids(const CSG_Grid_System & System,const CSG_Table & Attributes,int zAttribute,TSG_Data_Type Type,bool bCreateGrids)214 CSG_Grids::CSG_Grids(const CSG_Grid_System &System, const CSG_Table &Attributes, int zAttribute, TSG_Data_Type Type, bool bCreateGrids)
215 {
216 	_On_Construction();
217 
218 	Create(System, Attributes, zAttribute, Type, bCreateGrids);
219 }
220 
221 
222 ///////////////////////////////////////////////////////////
223 //														 //
224 ///////////////////////////////////////////////////////////
225 
226 //---------------------------------------------------------
_On_Construction(void)227 void CSG_Grids::_On_Construction(void)
228 {
229 	m_pGrids	= (CSG_Grid **)m_Grids.Create(1);
230 	m_pGrids[0]	= SG_Create_Grid();	// The Dummy
231 	m_pGrids[0]->Set_Owner(this);
232 
233 	m_Attributes.Set_Owner(this);
234 
235 	m_Index		= NULL;
236 
237 	Destroy();
238 
239 	Set_Update_Flag();
240 }
241 
242 //---------------------------------------------------------
243 /**
244   * Destroys the data space of the CSG_Grids object.
245 */
Destroy(void)246 bool CSG_Grids::Destroy(void)
247 {
248 	for(size_t i=1; i<m_Grids.Get_Size(); i++)
249 	{
250 		delete(m_pGrids[i]);	// do not delete the dummy before deconstruction
251 	}
252 
253 	m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(1);
254 
255 	m_pGrids[0]->Destroy();	// The Dummy
256 
257 	SG_FREE_SAFE(m_Index);
258 
259 	m_Attributes.Destroy();
260 	m_Attributes.Add_Field("Z", SG_DATATYPE_Double);
261 	m_Z_Attribute	= m_Z_Name	= 0;
262 
263 	return( CSG_Data_Object::Destroy() );
264 }
265 
266 
267 ///////////////////////////////////////////////////////////
268 //														 //
269 ///////////////////////////////////////////////////////////
270 
271 //---------------------------------------------------------
Create(const CSG_Grids & Grids)272 bool CSG_Grids::Create(const CSG_Grids &Grids)
273 {
274 	return( Create((CSG_Grids *)&Grids, true) );
275 }
276 
277 //---------------------------------------------------------
Create(const CSG_Grids * pGrids,bool bCopyData)278 bool CSG_Grids::Create(const CSG_Grids *pGrids, bool bCopyData)
279 {
280 	if( pGrids && pGrids->is_Valid() && Create(pGrids->Get_System(), 0, 0., pGrids->Get_Type()) )
281 	{
282 		Set_NoData_Value_Range(pGrids->Get_NoData_Value(), pGrids->Get_NoData_Value(true));
283 
284 		m_Attributes.Create(&pGrids->m_Attributes);
285 		Set_Z_Attribute (pGrids->Get_Z_Attribute ());
286 		Set_Z_Name_Field(pGrids->Get_Z_Name_Field());
287 
288 		if( bCopyData )
289 		{
290 			for(int i=0; i<pGrids->Get_NZ(); i++)
291 			{
292 				Add_Grid(pGrids->Get_Attributes(i), pGrids->Get_Grid_Ptr(i));
293 			}
294 		}
295 
296 		Get_MetaData_DB().Del_Children();
297 		Get_MetaData_DB().Add_Children(pGrids->Get_MetaData_DB());
298 
299 		Get_Projection().Create(pGrids->Get_Projection());
300 
301 		return( true );
302 	}
303 
304 	return( false );
305 }
306 
307 //---------------------------------------------------------
Create(const CSG_String & FileName,bool bLoadData)308 bool CSG_Grids::Create(const CSG_String &FileName, bool bLoadData)
309 {
310 	return( Load(FileName, bLoadData) );
311 }
312 
313 //---------------------------------------------------------
Create(const CSG_Grid_System & System,int NZ,double zMin,TSG_Data_Type Type)314 bool CSG_Grids::Create(const CSG_Grid_System &System, int NZ, double zMin, TSG_Data_Type Type)
315 {
316 	Destroy();
317 
318 	if( m_pGrids[0]->Create(System, Type) )
319 	{
320 		Set_NoData_Value_Range(m_pGrids[0]->Get_NoData_Value(), m_pGrids[0]->Get_NoData_Value(true));
321 
322 		for(int i=0; i<NZ; i++, zMin+=System.Get_Cellsize())
323 		{
324 			if( !Add_Grid(zMin) )
325 			{
326 				return( false );
327 			}
328 		}
329 
330 		return( true );
331 	}
332 
333 	return( false );
334 }
335 
336 //---------------------------------------------------------
Create(const CSG_Grid_System & System,const CSG_Table & Attributes,int zAttribute,TSG_Data_Type Type,bool bCreateGrids)337 bool CSG_Grids::Create(const CSG_Grid_System &System, const CSG_Table &Attributes, int zAttribute, TSG_Data_Type Type, bool bCreateGrids)
338 {
339 	Destroy();
340 
341 	if( m_Attributes.Create(&Attributes) && m_pGrids[0]->Create(System, Type) )
342 	{
343 		Set_Z_Attribute(zAttribute);
344 
345 		if( bCreateGrids )
346 		{
347 			for(int i=0; i<Attributes.Get_Count(); i++)
348 			{
349 				if( !Add_Grid(Attributes[i]) )
350 				{
351 					return( false );
352 				}
353 			}
354 		}
355 
356 		return( true );
357 	}
358 
359 	return( false );
360 }
361 
362 //---------------------------------------------------------
Create(int NX,int NY,int NZ,double Cellsize,double xMin,double yMin,double zMin,TSG_Data_Type Type)363 bool CSG_Grids::Create(int NX, int NY, int NZ, double Cellsize, double xMin, double yMin, double zMin, TSG_Data_Type Type)
364 {
365 	return( Create(CSG_Grid_System(Cellsize, xMin, yMin, NX, NY), NZ, zMin, Type) );
366 }
367 
368 
369 ///////////////////////////////////////////////////////////
370 //														 //
371 //						Header							 //
372 //														 //
373 ///////////////////////////////////////////////////////////
374 
375 //---------------------------------------------------------
Set_Unit(const CSG_String & Unit)376 void CSG_Grids::Set_Unit(const CSG_String &Unit)
377 {
378 	m_pGrids[0]->Set_Unit(Unit);
379 }
380 
381 //---------------------------------------------------------
Set_Scaling(double Scale,double Offset)382 void CSG_Grids::Set_Scaling(double Scale, double Offset)
383 {
384 	m_pGrids[0]->Set_Scaling(Scale, Offset);
385 
386 	for(int i=1; i<Get_Grid_Count(); i++)
387 	{
388 		m_pGrids[i]->Set_Scaling(Scale, Offset);
389 	}
390 
391 	Set_Update_Flag();
392 }
393 
394 //---------------------------------------------------------
Set_NoData_Value_Range(double loValue,double hiValue)395 bool CSG_Grids::Set_NoData_Value_Range(double loValue, double hiValue)
396 {
397 	if( CSG_Data_Object::Set_NoData_Value_Range(loValue, hiValue) )	// this is a CSG_Data_Object base class property
398 	{
399 		m_pGrids[0]->Set_NoData_Value_Range(loValue, hiValue);
400 
401 		for(int i=1; i<Get_Grid_Count(); i++)
402 		{
403 			m_pGrids[i]->Set_NoData_Value_Range(loValue, hiValue);
404 		}
405 
406 		return( true );
407 	}
408 
409 	return( false );
410 }
411 
412 //---------------------------------------------------------
_Synchronize(CSG_Grid * pGrid)413 void CSG_Grids::_Synchronize(CSG_Grid *pGrid)
414 {
415 	if( !Get_Projection().is_Okay() && pGrid->Get_Projection().is_Okay() )
416 	{
417 		Get_Projection().Create(pGrid->Get_Projection());
418 	}
419 
420 	pGrid->Set_Owner(this);
421 
422 	if( pGrid == m_pGrids[0] )
423 	{
424 		Set_Scaling(pGrid->Get_Scaling(), pGrid->Get_Offset());
425 		Set_NoData_Value_Range(pGrid->Get_NoData_Value(), pGrid->Get_NoData_Value(true));
426 	}
427 	else // if( pGrid != m_pGrids[0] )
428 	{
429 		pGrid->Set_Scaling(Get_Scaling(), Get_Offset());
430 		pGrid->Set_NoData_Value_Range(Get_NoData_Value(), Get_NoData_Value(true));
431 	}
432 }
433 
434 
435 ///////////////////////////////////////////////////////////
436 //														 //
437 //						Checks							 //
438 //														 //
439 ///////////////////////////////////////////////////////////
440 
441 //---------------------------------------------------------
is_Valid(void) const442 bool CSG_Grids::is_Valid(void) const
443 {
444 	return( Get_System().is_Valid() );
445 }
446 
447 //---------------------------------------------------------
is_Compatible(CSG_Grid * pGrid) const448 bool CSG_Grids::is_Compatible(CSG_Grid *pGrid) const
449 {
450 	return( pGrid && is_Compatible(pGrid->Get_System()) && Get_Type() == pGrid->Get_Type() );
451 }
452 
is_Compatible(CSG_Grids * pGrids) const453 bool CSG_Grids::is_Compatible(CSG_Grids *pGrids) const
454 {
455 	return( pGrids && is_Compatible(pGrids->Get_System()) && Get_NZ() == pGrids->Get_NZ() );//&& Get_Type() == pGrids->Get_Type() );
456 }
457 
is_Compatible(const CSG_Grid_System & System) const458 bool CSG_Grids::is_Compatible(const CSG_Grid_System &System) const
459 {
460 	return( Get_System() == System );
461 }
462 
is_Compatible(int NX,int NY,double Cellsize,double xMin,double yMin) const463 bool CSG_Grids::is_Compatible(int NX, int NY, double Cellsize, double xMin, double yMin) const
464 {
465 	return(	is_Compatible(CSG_Grid_System(Cellsize, xMin, yMin, NX, NY)) );
466 }
467 
468 
469 ///////////////////////////////////////////////////////////
470 //														 //
471 //						Attributes						 //
472 //														 //
473 ///////////////////////////////////////////////////////////
474 
475 //---------------------------------------------------------
Add_Attribute(const CSG_String & Name,TSG_Data_Type Type,int i)476 bool CSG_Grids::Add_Attribute(const CSG_String &Name, TSG_Data_Type Type, int i)
477 {
478 	return( m_Attributes.Add_Field(Name, Type, i) );
479 }
480 
481 //---------------------------------------------------------
Del_Attribute(int i)482 bool CSG_Grids::Del_Attribute(int i)
483 {
484 	if( i != m_Z_Attribute && m_Attributes.Get_Field_Count() > 0 && m_Attributes.Del_Field(i) )
485 	{
486 		if( m_Z_Attribute > i )
487 		{
488 			m_Z_Attribute--;
489 		}
490 
491 		if( m_Z_Name > i )
492 		{
493 			m_Z_Name--;
494 		}
495 		else if( m_Z_Name == i )
496 		{
497 			m_Z_Name	= -1;	// same as m_Z_Attribute
498 		}
499 
500 		return( true );
501 	}
502 
503 	return( false );
504 }
505 
506 //---------------------------------------------------------
Set_Z_Attribute(int i)507 bool CSG_Grids::Set_Z_Attribute(int i)
508 {
509 	if( i >= 0 && i < m_Attributes.Get_Field_Count() )
510 	{
511 		m_Z_Attribute	= i;
512 
513 		return( Update_Z_Order() );
514 	}
515 
516 	return( false );
517 }
518 
519 //---------------------------------------------------------
Set_Z_Name_Field(int i)520 bool CSG_Grids::Set_Z_Name_Field(int i)
521 {
522 	if( i >= 0 && i < m_Attributes.Get_Field_Count() )
523 	{
524 		m_Z_Name	= i;
525 
526 		return( true );
527 	}
528 
529 	return( false );
530 }
531 
Get_Z_Name_Field(void) const532 int CSG_Grids::Get_Z_Name_Field(void)	const
533 {
534 	return( m_Z_Name >= 0 && m_Z_Name < m_Attributes.Get_Field_Count() ? m_Z_Name : m_Z_Attribute );
535 }
536 
537 //---------------------------------------------------------
Set_Z(int i,double Value)538 bool CSG_Grids::Set_Z(int i, double Value)
539 {
540 	return( i >= 0 && i < Get_NZ() && m_Attributes[i].Set_Value(m_Z_Attribute, Value) );
541 }
542 
543 //---------------------------------------------------------
Update_Z_Order(void)544 bool CSG_Grids::Update_Z_Order(void)
545 {
546 	bool	bChanged	= false;
547 
548 	CSG_Table	Attributes(m_Attributes);
549 
550 	if( Attributes.Set_Index(m_Z_Attribute, TABLE_INDEX_Ascending) )
551 	{
552 		CSG_Array_Pointer	Grids;
553 
554 		CSG_Grid	**pGrids	= (CSG_Grid **)Grids.Create(m_Grids);
555 
556 		for(int i=0; i<Get_Grid_Count(); i++)
557 		{
558 			int	Index	= Attributes[i].Get_Index();
559 
560 			if( Index != i )
561 			{
562 				bChanged	= true;
563 
564 				m_pGrids[i]	= pGrids[Index];
565 
566 				m_Attributes[i].Assign(&Attributes[i]);
567 			}
568 		}
569 
570 		for(int i=0; i<Get_Grid_Count(); i++)
571 		{
572 			pGrids[i]->Set_Name(Get_Grid_Name(i));
573 		}
574 	}
575 
576 	return( bChanged );
577 }
578 
579 
580 ///////////////////////////////////////////////////////////
581 //														 //
582 //														 //
583 //														 //
584 ///////////////////////////////////////////////////////////
585 
586 //---------------------------------------------------------
Set_Grid_Count(int Count)587 bool CSG_Grids::Set_Grid_Count(int Count)
588 {
589 	if( Count == Get_NZ() )
590 	{
591 		return( true );
592 	}
593 
594 	if( Count < 0 || !Get_System().is_Valid() )	// only allowed for initialized grid systems)
595 	{
596 		return( false );
597 	}
598 
599 	if( Count == 0 )
600 	{
601 		return( Del_Grids() );
602 	}
603 
604 	//-----------------------------------------------------
605 	SG_FREE_SAFE(m_Index);	// invalidate index
606 
607 	if( Count < Get_NZ() )
608 	{
609 		for(int i=Count; i<Get_NZ(); i++)
610 		{
611 			delete(m_pGrids[i]);
612 		}
613 
614 		m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(Count);
615 
616 		m_Attributes.Set_Record_Count(Count);
617 	}
618 
619 	//-----------------------------------------------------
620 	else if( Count > Get_NZ() )
621 	{
622 		double	z	= Get_ZMax();
623 
624 		for(int i=Get_NZ(); i<=Count; i++, z+=Get_Cellsize())
625 		{
626 			if( !Add_Grid(z) )
627 			{
628 				return( false );
629 			}
630 		}
631 	}
632 
633 	return( true );
634 }
635 
636 
637 ///////////////////////////////////////////////////////////
638 //														 //
639 ///////////////////////////////////////////////////////////
640 
641 //---------------------------------------------------------
Add_Grid(double Z)642 bool CSG_Grids::Add_Grid(double Z)
643 {
644 	CSG_Table	Attributes(&m_Attributes);
645 
646 	Attributes.Add_Record();
647 
648 	Attributes[0].Set_Value(m_Z_Attribute, Z);
649 
650 	return( Add_Grid(Attributes[0]) );
651 }
652 
653 //---------------------------------------------------------
Add_Grid(double Z,CSG_Grid * pGrid,bool bAttach)654 bool CSG_Grids::Add_Grid(double Z, CSG_Grid *pGrid, bool bAttach)
655 {
656 	CSG_Table	Attributes(&m_Attributes);
657 
658 	Attributes.Add_Record();
659 
660 	Attributes[0].Set_Value(m_Z_Attribute, Z);
661 
662 	return( Add_Grid(Attributes[0], pGrid, bAttach) );
663 }
664 
665 //---------------------------------------------------------
Add_Grid(CSG_Table_Record & Attributes)666 bool CSG_Grids::Add_Grid(CSG_Table_Record &Attributes)
667 {
668 	if( !Get_System().is_Valid() )	// only allowed for initialized grid systems
669 	{
670 		return( false );
671 	}
672 
673 	//-----------------------------------------------------
674 	int	n	= Get_NZ();
675 
676 	if( n < 1 )	// do some initializations
677 	{
678 		_Synchronize(m_pGrids[0]);
679 	}
680 	else // use dummy grid (m_pGrids[0] is always present)
681 	{
682 		CSG_Grid	*pGrid	= SG_Create_Grid(Get_System(), Get_Type());
683 
684 		if( !pGrid )
685 		{
686 			return( false );
687 		}
688 
689 		m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(n + 1);
690 		m_pGrids[n]	= pGrid;
691 
692 		_Synchronize(pGrid);
693 	}
694 
695 	//-----------------------------------------------------
696 	m_Attributes.Add_Record(&Attributes);
697 
698 	SG_FREE_SAFE(m_Index);	// invalidate index
699 
700 	Update_Z_Order();
701 
702 	return( true );
703 }
704 
705 //---------------------------------------------------------
Add_Grid(CSG_Table_Record & Attributes,CSG_Grid * pGrid,bool bAttach)706 bool CSG_Grids::Add_Grid(CSG_Table_Record &Attributes, CSG_Grid *pGrid, bool bAttach)
707 {
708 	if( !pGrid || !pGrid->is_Valid() )
709 	{
710 		return( false );
711 	}
712 
713 	if( Get_NZ() > 0 && !is_Compatible(pGrid) )	// not allowed
714 	{
715 		return( false );
716 	}
717 
718 	//-----------------------------------------------------
719 	int	n	= Get_NZ();
720 
721 	if( n > 0 )
722 	{
723 		if( !bAttach && (pGrid = SG_Create_Grid(*pGrid)) == NULL )	// get a copy
724 		{
725 			return( false );
726 		}
727 
728 		m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(n + 1);
729 		m_pGrids[n]	= pGrid;
730 	}
731 	else if( bAttach ) // if( n == 0 )
732 	{
733 		delete(m_pGrids[0]);
734 
735 		m_pGrids[0]	= pGrid;	// simply replace dummy
736 	}
737 	else if( m_pGrids[0]->Create(*pGrid) )	// make dummy a copy of grid
738 	{
739 		pGrid	= m_pGrids[0];
740 	}
741 	else
742 	{
743 		return( false );
744 	}
745 
746 	_Synchronize(pGrid);
747 
748 	//-----------------------------------------------------
749 	m_Attributes.Add_Record(&Attributes);
750 
751 	if( !Get_Projection().is_Okay() && pGrid->Get_Projection().is_Okay() )
752 	{
753 		Get_Projection()	= pGrid->Get_Projection();
754 	}
755 
756 	SG_FREE_SAFE(m_Index);	// invalidate index
757 
758 	Update_Z_Order();
759 
760 	return( true );
761 }
762 
763 
764 ///////////////////////////////////////////////////////////
765 //														 //
766 ///////////////////////////////////////////////////////////
767 
768 //---------------------------------------------------------
Del_Grid(int i,bool bDetach)769 bool CSG_Grids::Del_Grid(int i, bool bDetach)
770 {
771 	if( m_Attributes.Del_Record(i) )	// Get_NZ() is now decreased by one
772 	{
773 		SG_FREE_SAFE(m_Index);	// invalidate index
774 
775 		if( Get_NZ() > 0 )
776 		{
777 			if( bDetach )
778 			{
779 				m_pGrids[i]->Set_Owner(NULL);
780 			}
781 			else
782 			{
783 				delete(m_pGrids[i]);
784 			}
785 
786 			for( ; i<Get_NZ(); i++)
787 			{
788 				m_pGrids[i]	= m_pGrids[i + 1];
789 			}
790 
791 			m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(Get_NZ());
792 		}
793 		else if( bDetach ) // if( Get_NZ() == 0 )
794 		{
795 			m_pGrids[0]->Set_Owner(NULL);
796 			m_pGrids[0]	= SG_Create_Grid(*m_pGrids[0]);	// needs a new dummy
797 			m_pGrids[0]->Set_Owner(this);
798 		}
799 
800 		return( true );
801 	}
802 
803 	return( false );
804 }
805 
806 //---------------------------------------------------------
Del_Grids(bool bDetach)807 bool CSG_Grids::Del_Grids(bool bDetach)
808 {
809 	SG_FREE_SAFE(m_Index);	// invalidate index
810 
811 	if( bDetach )
812 	{
813 		for(size_t i=0; i<m_Grids.Get_Size(); i++)
814 		{
815 			if( m_pGrids[i]->Get_Owner() == this )
816 			{
817 				m_pGrids[i]->Set_Owner(NULL);
818 			}
819 		}
820 
821 		m_pGrids[0]	= SG_Create_Grid(*m_pGrids[0]);	// needs a new dummy
822 		m_pGrids[0]->Set_Owner(this);
823 	}
824 	else
825 	{
826 		for(size_t i=1; i<m_Grids.Get_Size(); i++)
827 		{
828 			delete(m_pGrids[i]);	// do not delete the dummy before deconstruction
829 		}
830 	}
831 
832 	m_pGrids	= (CSG_Grid **)m_Grids.Get_Array(1);
833 
834 	m_Attributes.Del_Records();
835 
836 	return( true );
837 }
838 
839 
840 ///////////////////////////////////////////////////////////
841 //														 //
842 ///////////////////////////////////////////////////////////
843 
844 //---------------------------------------------------------
Get_Grid_Name(int i,int Style) const845 CSG_String CSG_Grids::Get_Grid_Name(int i, int Style) const
846 {
847 	CSG_String	s;
848 
849 	if( i >= 0 && i < Get_Grid_Count() )
850 	{
851 		if( Style == 0 )
852 		{
853 			Style	= SG_GRIDS_NAME_OWNER|SG_GRIDS_NAME_GRID;
854 		}
855 
856 		if( (Style & SG_GRIDS_NAME_OWNER) != 0 )
857 		{
858 			s	= CSG_String(Get_Name());
859 		}
860 
861 		if( (Style & SG_GRIDS_NAME_INDEX) != 0 )
862 		{
863 			if( !s.is_Empty() )	s	+= ".";
864 
865 			s.Printf("%s %d", _TL("Band"), i + 1);
866 		}
867 
868 		if( (Style & SG_GRIDS_NAME_VALUE) != 0 )
869 		{
870 			if( !s.is_Empty() )	s	+= ".";
871 
872 			s	+= SG_Get_String(Get_Z(i), -10);
873 		}
874 
875 		if( (Style & SG_GRIDS_NAME_GRID ) != 0 )
876 		{
877 			if( !s.is_Empty() )	s	+= ".";
878 
879 			s	+= m_Attributes[i].asString(Get_Z_Name_Field());
880 		}
881 	}
882 
883 	return( s );
884 }
885 
886 
887 ///////////////////////////////////////////////////////////
888 //														 //
889 //														 //
890 //														 //
891 ///////////////////////////////////////////////////////////
892 
893 //---------------------------------------------------------
Assign_NoData(void)894 void CSG_Grids::Assign_NoData(void)
895 {
896 	for(int i=0; i<Get_Grid_Count(); i++)
897 	{
898 		m_pGrids[i]->Assign_NoData();
899 	}
900 }
901 
902 //---------------------------------------------------------
Assign(double Value)903 bool CSG_Grids::Assign(double Value)
904 {
905 	for(int i=0; i<Get_Grid_Count(); i++)
906 	{
907 		m_pGrids[i]->Assign(Value);
908 	}
909 
910 	return( true );
911 }
912 
913 //---------------------------------------------------------
Assign(CSG_Data_Object * pObject)914 bool CSG_Grids::Assign(CSG_Data_Object *pObject)
915 {
916 	if( pObject )
917 	{
918 		switch( pObject->Get_ObjectType() )
919 		{
920 		case SG_DATAOBJECT_TYPE_Grid:
921 			{
922 				bool	bResult	= true;
923 
924 				for(int i=0; i<Get_Grid_Count(); i++)
925 				{
926 					if( !m_pGrids[i]->Assign((CSG_Grid *)pObject) )
927 					{
928 						bResult	= false;
929 					}
930 				}
931 
932 				return( bResult );
933 			}
934 
935 		case SG_DATAOBJECT_TYPE_Grids:
936 			return( Assign((CSG_Grids *)pObject) );
937 
938 		default:
939 			break;
940 		}
941 	}
942 
943 	return( false );
944 }
945 
946 //---------------------------------------------------------
Assign(CSG_Grids * pGrids,TSG_Grid_Resampling Interpolation)947 bool CSG_Grids::Assign(CSG_Grids *pGrids, TSG_Grid_Resampling Interpolation)
948 {
949 	if( pGrids && Get_Grid_Count() == pGrids->Get_Grid_Count() )
950 	{
951 		bool	bResult	= true;
952 
953 		for(int i=0; i<Get_Grid_Count(); i++)
954 		{
955 			if( !m_pGrids[i]->Assign(pGrids->m_pGrids[i], Interpolation) )
956 			{
957 				bResult	= false;
958 			}
959 		}
960 
961 		return( bResult );
962 	}
963 
964 	return( false );
965 }
966 
967 
968 ///////////////////////////////////////////////////////////
969 //														 //
970 ///////////////////////////////////////////////////////////
971 
972 //---------------------------------------------------------
operator =(const CSG_Grids & Grids)973 CSG_Grids & CSG_Grids::operator = (const CSG_Grids &Grids)
974 {
975 	Create(Grids); return( *this );
976 }
977 
operator =(double Value)978 CSG_Grids & CSG_Grids::operator = (double Value)
979 {
980 	Assign(Value); return( *this );
981 }
982 
983 //---------------------------------------------------------
operator +=(double Value)984 CSG_Grids & CSG_Grids::operator += (double Value)
985 {
986 	return( Add(Value) );
987 }
988 
Add(double Value)989 CSG_Grids & CSG_Grids::Add(double Value)
990 {
991 	for(int i=0; i<Get_Grid_Count(); i++)
992 	{
993 		m_pGrids[i]->Add(Value);
994 	}
995 
996 	return( *this );
997 }
998 
999 //---------------------------------------------------------
operator -=(double Value)1000 CSG_Grids & CSG_Grids::operator -= (double Value)
1001 {
1002 	return( Subtract(Value) );
1003 }
1004 
Subtract(double Value)1005 CSG_Grids & CSG_Grids::Subtract(double Value)
1006 {
1007 	for(int i=0; i<Get_Grid_Count(); i++)
1008 	{
1009 		m_pGrids[i]->Subtract(Value);
1010 	}
1011 
1012 	return( *this );
1013 }
1014 
1015 //---------------------------------------------------------
operator *=(double Value)1016 CSG_Grids & CSG_Grids::operator *= (double Value)
1017 {
1018 	return( Multiply(Value) );
1019 }
1020 
Multiply(double Value)1021 CSG_Grids & CSG_Grids::Multiply(double Value)
1022 {
1023 	for(int i=0; i<Get_Grid_Count(); i++)
1024 	{
1025 		m_pGrids[i]->Multiply(Value);
1026 	}
1027 
1028 	return( *this );
1029 }
1030 
1031 //---------------------------------------------------------
operator /=(double Value)1032 CSG_Grids & CSG_Grids::operator /= (double Value)
1033 {
1034 	return( Divide(Value) );
1035 }
1036 
Divide(double Value)1037 CSG_Grids & CSG_Grids::Divide(double Value)
1038 {
1039 	for(int i=0; i<Get_Grid_Count(); i++)
1040 	{
1041 		m_pGrids[i]->Divide(Value);
1042 	}
1043 
1044 	return( *this );
1045 }
1046 
1047 
1048 ///////////////////////////////////////////////////////////
1049 //														 //
1050 //		Value access by Position (-> Interpolation)		 //
1051 //														 //
1052 ///////////////////////////////////////////////////////////
1053 
1054 //---------------------------------------------------------
Get_Value(const TSG_Point_Z & p,TSG_Grid_Resampling Resampling,TSG_Grid_Resampling ZResampling) const1055 double CSG_Grids::Get_Value(const TSG_Point_Z &p, TSG_Grid_Resampling Resampling, TSG_Grid_Resampling ZResampling) const
1056 {
1057 	double	Value;
1058 
1059 	return( Get_Value(p.x, p.y, p.z, Value, Resampling, ZResampling) ? Value : Get_NoData_Value() );
1060 }
1061 
Get_Value(double x,double y,double z,TSG_Grid_Resampling Resampling,TSG_Grid_Resampling ZResampling) const1062 double CSG_Grids::Get_Value(double x, double y, double z, TSG_Grid_Resampling Resampling, TSG_Grid_Resampling ZResampling) const
1063 {
1064 	double	Value;
1065 
1066 	return( Get_Value(x, y, z, Value, Resampling, ZResampling) ? Value : Get_NoData_Value() );
1067 }
1068 
Get_Value(const TSG_Point_Z & p,double & Value,TSG_Grid_Resampling Resampling,TSG_Grid_Resampling ZResampling) const1069 bool CSG_Grids::Get_Value(const TSG_Point_Z &p, double &Value, TSG_Grid_Resampling Resampling, TSG_Grid_Resampling ZResampling) const
1070 {
1071 	return( Get_Value(p.x, p.y, p.z, Value, Resampling, ZResampling) );
1072 }
1073 
1074 //---------------------------------------------------------
Get_Value(double x,double y,double z,double & Value,TSG_Grid_Resampling Resampling,TSG_Grid_Resampling ZResampling) const1075 bool CSG_Grids::Get_Value(double x, double y, double z, double &Value, TSG_Grid_Resampling Resampling, TSG_Grid_Resampling ZResampling) const
1076 {
1077 	if(	!Get_System().Get_Extent(true).Contains(x, y) )
1078 	{
1079 		return( false );
1080 	}
1081 
1082 	int	iz;	double	dz;
1083 
1084 	if( !_Get_Z(z, iz, dz) )
1085 	{
1086 		return( false );
1087 	}
1088 
1089 	if( dz == 0. )
1090 	{
1091 		return( m_pGrids[iz]->Get_Value(x, y, Value, Resampling) );
1092 	}
1093 
1094 	if( ZResampling == GRID_RESAMPLING_Undefined )
1095 	{
1096 		ZResampling	= Resampling;
1097 	}
1098 
1099 	if( (ZResampling == GRID_RESAMPLING_BicubicSpline || ZResampling == GRID_RESAMPLING_BSpline)
1100 	&&  (iz < 1 || iz >= m_Attributes.Get_Count() - 2) )
1101 	{
1102 		ZResampling	= GRID_RESAMPLING_Bilinear;
1103 	}
1104 
1105 	switch( ZResampling )
1106 	{
1107 	case GRID_RESAMPLING_NearestNeighbour: default:
1108 		return( m_pGrids[dz < 0.5 ? iz : iz + 1]->Get_Value(x, y, Value, Resampling) );
1109 
1110 	case GRID_RESAMPLING_Bilinear:
1111 		{
1112 			double	v[2];
1113 
1114 			if( m_pGrids[iz    ]->Get_Value(x, y, v[0], Resampling)
1115 			&&  m_pGrids[iz + 1]->Get_Value(x, y, v[1], Resampling) )
1116 			{
1117 				Value	= v[0] + dz * (v[1] - v[0]);
1118 
1119 				return( true );
1120 			}
1121 
1122 			return( false );
1123 		}
1124 
1125 	case GRID_RESAMPLING_BicubicSpline:
1126 	case GRID_RESAMPLING_BSpline:
1127 		{
1128 			CSG_Spline	s;
1129 
1130 			#define ADD_TO_SPLINE(i)	if( i < 0 || i >= Get_NZ() || !m_pGrids[i]->Get_Value(x, y, Value, Resampling) ) return( false ); s.Add(Get_Z(i), Value);
1131 
1132 			ADD_TO_SPLINE(iz - 1);
1133 			ADD_TO_SPLINE(iz    );
1134 			ADD_TO_SPLINE(iz + 1);
1135 			ADD_TO_SPLINE(iz + 2);
1136 
1137 			return( s.Get_Value(z, Value) );
1138 		}
1139 		break;
1140 	}
1141 
1142 	return( false );
1143 }
1144 
1145 //---------------------------------------------------------
_Get_Z(double z,int & iz,double & dz) const1146 bool CSG_Grids::_Get_Z(double z, int &iz, double &dz) const
1147 {
1148 	if( z < m_Attributes[0                           ].asDouble(m_Z_Attribute)
1149 	||  z > m_Attributes[m_Attributes.Get_Count() - 1].asDouble(m_Z_Attribute) )
1150 	{
1151 		return( false );
1152 	}
1153 
1154 	double	z0, z1	= m_Attributes[0].asDouble(m_Z_Attribute);
1155 
1156 	for(iz=0; iz<m_Attributes.Get_Count()-1; iz++)
1157 	{
1158 		z0 = z1; z1	= m_Attributes[iz + 1].asDouble(m_Z_Attribute);
1159 
1160 		if( z < z1 )
1161 		{
1162 			dz	= z0 < z1 ? (z - z0) / (z1 - z0) : 0.;
1163 
1164 			return( true );
1165 		}
1166 	}
1167 
1168 	return( (dz = z - z1) == 0. );
1169 }
1170 
1171 
1172 ///////////////////////////////////////////////////////////
1173 //														 //
1174 //						Index							 //
1175 //														 //
1176 ///////////////////////////////////////////////////////////
1177 
1178 //---------------------------------------------------------
1179 #define SORT_SWAP(a,b)	{itemp=(a);(a)=(b);(b)=itemp;}
1180 
_Set_Index(void)1181 bool CSG_Grids::_Set_Index(void)
1182 {
1183 	//-----------------------------------------------------
1184 	if( m_Index == NULL && (m_Index = (sLong *)SG_Malloc((size_t)Get_NCells() * sizeof(sLong))) == NULL )
1185 	{
1186 		SG_UI_Msg_Add_Error(_TL("could not create index: insufficient memory"));
1187 
1188 		return( false );
1189 	}
1190 
1191 	//-----------------------------------------------------
1192 	const sLong	M	= 7;
1193 
1194 	sLong	i, j, k, l, ir, n, *istack, jstack, nstack, indxt, itemp, nData;
1195 	double	a;
1196 
1197 	//-----------------------------------------------------
1198 	SG_UI_Process_Set_Text(CSG_String::Format("%s: %s", _TL("Create index"), Get_Name()));
1199 
1200 	for(i=0, j=0, nData=Get_NCells(); i<Get_NCells(); i++)
1201 	{
1202 		if( is_NoData(i) )
1203 		{
1204 			m_Index[--nData]	= i;
1205 		}
1206 		else // if( !is_NoData(i) )
1207 		{
1208 			m_Index[j++]	= i;
1209 		}
1210 	}
1211 
1212 	//-----------------------------------------------------
1213 	l		= 0;
1214 	n		= 0;
1215 	ir		= nData - 1;
1216 
1217 	nstack	= 64;
1218 	istack	= (sLong *)SG_Malloc((size_t)nstack * sizeof(sLong));
1219 	jstack	= 0;
1220 
1221 	for(;;)
1222 	{
1223 		if( ir - l < M )
1224 		{
1225 			if( !SG_UI_Process_Set_Progress((double)(n += M - 1), (double)nData) )
1226 			{
1227 				SG_FREE_SAFE(istack);
1228 				SG_FREE_SAFE(m_Index);
1229 
1230 				SG_UI_Msg_Add_Error(_TL("index creation stopped by user"));
1231 				SG_UI_Process_Set_Ready();
1232 
1233 				return( false );
1234 			}
1235 
1236 			for(j=l+1; j<=ir; j++)
1237 			{
1238 				indxt	= m_Index[j];
1239 				a		= asDouble(indxt);
1240 
1241 				for(i=j-1; i>=0; i--)
1242 				{
1243 					if( asDouble(m_Index[i]) <= a )
1244 					{
1245 						break;
1246 					}
1247 
1248 					m_Index[i + 1]	= m_Index[i];
1249 				}
1250 
1251 				m_Index[i + 1]	= indxt;
1252 			}
1253 
1254 			if( jstack == 0 )
1255 			{
1256 				break;
1257 			}
1258 
1259 			ir		= istack[jstack--];
1260 			l		= istack[jstack--];
1261 		}
1262 
1263 		//-------------------------------------------------
1264 		else
1265 		{
1266 			k		= (l + ir) >> 1;
1267 
1268 			SORT_SWAP(m_Index[k], m_Index[l + 1]);
1269 
1270 			if( asDouble( m_Index[l + 1]) > asDouble(m_Index[ir]) )
1271 				SORT_SWAP(m_Index[l + 1],            m_Index[ir]);
1272 
1273 			if( asDouble( m_Index[l    ]) > asDouble(m_Index[ir]) )
1274 				SORT_SWAP(m_Index[l    ],            m_Index[ir]);
1275 
1276 			if( asDouble( m_Index[l + 1]) > asDouble(m_Index[l ]) )
1277 				SORT_SWAP(m_Index[l + 1],            m_Index[l ]);
1278 
1279 			i		= l + 1;
1280 			j		= ir;
1281 			indxt	= m_Index[l];
1282 			a		= asDouble(indxt);
1283 
1284 			for(;;)
1285 			{
1286 				do	i++;	while(asDouble(m_Index[i]) < a);
1287 				do	j--;	while(asDouble(m_Index[j]) > a);
1288 
1289 				if( j < i )
1290 				{
1291 					break;
1292 				}
1293 
1294 				SORT_SWAP(m_Index[i], m_Index[j]);
1295 			}
1296 
1297 			m_Index[l]	= m_Index[j];
1298 			m_Index[j]	= indxt;
1299 			jstack		+= 2;
1300 
1301 			if( jstack >= nstack )
1302 			{
1303 				nstack	+= 64;
1304 				istack	= (sLong *)SG_Realloc(istack, (size_t)nstack * sizeof(int));
1305 			}
1306 
1307 			if( ir - i + 1 >= j - l )
1308 			{
1309 				istack[jstack]		= ir;
1310 				istack[jstack - 1]	= i;
1311 				ir					= j - 1;
1312 			}
1313 			else
1314 			{
1315 				istack[jstack]		= j - 1;
1316 				istack[jstack - 1]	= l;
1317 				l					= i;
1318 			}
1319 		}
1320 	}
1321 
1322 	//-----------------------------------------------------
1323 	SG_Free(istack);
1324 
1325 	SG_UI_Process_Set_Ready();
1326 
1327 	return( true );
1328 }
1329 #undef SORT_SWAP
1330 
1331 
1332 ///////////////////////////////////////////////////////////
1333 //														 //
1334 //						Statistics						 //
1335 //														 //
1336 ///////////////////////////////////////////////////////////
1337 
1338 //---------------------------------------------------------
On_Update(void)1339 bool CSG_Grids::On_Update(void)
1340 {
1341 	if( is_Valid() )
1342 	{
1343 		SG_FREE_SAFE(m_Index);
1344 
1345 		m_Statistics.Invalidate();
1346 		m_Histogram.Destroy();
1347 
1348 		double	Offset = Get_Offset(), Scaling = is_Scaled() ? Get_Scaling() : 0.;
1349 
1350 		if( Get_Max_Samples() > 0 && Get_Max_Samples() < Get_NCells() )
1351 		{
1352 			double	d	= (double)Get_NCells() / (double)Get_Max_Samples();
1353 
1354 			for(double i=0; i<(double)Get_NCells(); i+=d)
1355 			{
1356 				double	Value	= asDouble((sLong)i, false);
1357 
1358 				if( !is_NoData_Value(Value) )
1359 				{
1360 					m_Statistics	+= Scaling ? Offset + Scaling * Value : Value;
1361 				}
1362 			}
1363 
1364 			m_Statistics.Set_Count(m_Statistics.Get_Count() >= Get_Max_Samples() ? Get_NCells()	// any no-data cells ?
1365 				: (sLong)(Get_NCells() * (double)m_Statistics.Get_Count() / (double)Get_Max_Samples())
1366 			);
1367 		}
1368 		else
1369 		{
1370 			for(sLong i=0; i<Get_NCells(); i++)
1371 			{
1372 				double	Value	= asDouble(i, false);
1373 
1374 				if( !is_NoData_Value(Value) )
1375 				{
1376 					m_Statistics	+= Scaling ? Offset + Scaling * Value : Value;
1377 				}
1378 			}
1379 		}
1380 	}
1381 
1382 	return( true );
1383 }
1384 
1385 //---------------------------------------------------------
Get_Mean(void)1386 double CSG_Grids::Get_Mean(void)
1387 {
1388 	Update();	return( m_Statistics.Get_Mean() );
1389 }
1390 
Get_Min(void)1391 double CSG_Grids::Get_Min(void)
1392 {
1393 	Update();	return( m_Statistics.Get_Minimum() );
1394 }
1395 
Get_Max(void)1396 double CSG_Grids::Get_Max(void)
1397 {
1398 	Update();	return( m_Statistics.Get_Maximum() );
1399 }
1400 
Get_Range(void)1401 double CSG_Grids::Get_Range(void)
1402 {
1403 	Update();	return( m_Statistics.Get_Range() );
1404 }
1405 
Get_StdDev(void)1406 double CSG_Grids::Get_StdDev(void)
1407 {
1408 	Update();	return( m_Statistics.Get_StdDev() );
1409 }
1410 
Get_Variance(void)1411 double CSG_Grids::Get_Variance(void)
1412 {
1413 	Update();	return( m_Statistics.Get_Variance() );
1414 }
1415 
1416 //---------------------------------------------------------
Get_Data_Count(void)1417 sLong CSG_Grids::Get_Data_Count(void)
1418 {
1419 	Update();	return( m_Statistics.Get_Count() );
1420 }
1421 
Get_NoData_Count(void)1422 sLong CSG_Grids::Get_NoData_Count(void)
1423 {
1424 	Update();	return( Get_NCells() - m_Statistics.Get_Count() );
1425 }
1426 
1427 //---------------------------------------------------------
Get_Quantile(double Quantile,bool bFromHistogram)1428 double CSG_Grids::Get_Quantile(double Quantile, bool bFromHistogram)
1429 {
1430 	if( Quantile <= 0. ) { return( Get_Min() ); }
1431 	if( Quantile >= 1. ) { return( Get_Max() ); }
1432 
1433 	if( bFromHistogram )
1434 	{
1435 		return( Get_Histogram().Get_Quantile(Quantile) );
1436 	}
1437 	else
1438 	{
1439 		sLong	n	= (sLong)(Quantile * (Get_Data_Count() - 1));
1440 
1441 		if( Get_Sorted(n, n, false) )
1442 		{
1443 			return( asDouble(n) );
1444 		}
1445 	}
1446 
1447 	return( Get_NoData_Value() );
1448 }
1449 
1450 //---------------------------------------------------------
Get_Percentile(double Percentile,bool bFromHistogram)1451 double CSG_Grids::Get_Percentile(double Percentile, bool bFromHistogram)
1452 {
1453 	return( Get_Quantile(0.01 * Percentile, bFromHistogram) );
1454 }
1455 
1456 
1457 ///////////////////////////////////////////////////////////
1458 //														 //
1459 ///////////////////////////////////////////////////////////
1460 
1461 //---------------------------------------------------------
1462 /**
1463   * Returns the statistics for the whole data set. It is
1464   * automatically updated if necessary. Statistics give no
1465   * access to parameters like quantiles that need values
1466   * to be kept internally. Use Get_Quantile() function instead.
1467 */
Get_Statistics(void)1468 const CSG_Simple_Statistics & CSG_Grids::Get_Statistics(void)
1469 {
1470 	Update();	return( m_Statistics );
1471 }
1472 
1473 //---------------------------------------------------------
1474 /**
1475   * Calculate statistics for the region specified with rWorld.
1476   * Returns false, if there is no overlapping. Set bHoldValues
1477   * to true, if you need to obtain quantiles.
1478 */
1479 //---------------------------------------------------------
Get_Statistics(const CSG_Rect & rWorld,CSG_Simple_Statistics & Statistics,bool bHoldValues) const1480 bool CSG_Grids::Get_Statistics(const CSG_Rect &rWorld, CSG_Simple_Statistics &Statistics, bool bHoldValues) const
1481 {
1482 	int	xMin	= Get_System().Get_xWorld_to_Grid(rWorld.Get_XMin()); if( xMin <  0        ) xMin = 0;
1483 	int	yMin	= Get_System().Get_yWorld_to_Grid(rWorld.Get_YMin()); if( yMin <  0        ) yMin = 0;
1484 	int	xMax	= Get_System().Get_xWorld_to_Grid(rWorld.Get_XMax()); if( xMax >= Get_NX() ) xMax = Get_NX() - 1;
1485 	int	yMax	= Get_System().Get_yWorld_to_Grid(rWorld.Get_YMax()); if( yMax >= Get_NY() ) yMax = Get_NY() - 1;
1486 
1487 	if( xMin > xMax || yMin > yMax )
1488 	{
1489 		return( false );	// no overlap
1490 	}
1491 
1492 	Statistics.Create(bHoldValues);
1493 
1494 	int		nx		= 1 + (xMax - xMin);
1495 	int		ny		= 1 + (yMax - yMin);
1496 	sLong	nCells	= nx * ny;
1497 
1498 	double	Offset = Get_Offset(), Scaling = is_Scaled() ? Get_Scaling() : 0.;
1499 
1500 	if( Get_Max_Samples() > 0 && Get_Max_Samples() < nCells )
1501 	{
1502 		double	d = (double)nCells / (double)Get_Max_Samples();
1503 
1504 		for(double i=0; i<(double)nCells; i+=d)
1505 		{
1506 			int	y	= yMin + (int)i / nx;
1507 			int	x	= xMin + (int)i % nx;
1508 
1509 			for(int z=0; z<Get_NZ(); z++)
1510 			{
1511 				double	Value	= asDouble(x, y, z, false);
1512 
1513 				if( !is_NoData_Value(Value) )
1514 				{
1515 					Statistics	+= Scaling ? Offset + Scaling * Value : Value;
1516 				}
1517 			}
1518 		}
1519 	}
1520 	else
1521 	{
1522 		for(int x=xMin; x<=xMax; x++)
1523 		{
1524 			for(int y=yMin; y<=yMax; y++)
1525 			{
1526 				for(int z=0; z<Get_NZ(); z++)
1527 				{
1528 					double	Value	= asDouble(x, y, z, false);
1529 
1530 					if( !is_NoData_Value(Value) )
1531 					{
1532 						Statistics	+= Scaling ? Offset + Scaling * Value : Value;
1533 					}
1534 				}
1535 			}
1536 		}
1537 	}
1538 
1539 	return( Statistics.Get_Count() > 0 );
1540 }
1541 
1542 //---------------------------------------------------------
Set_Max_Samples(sLong Max_Samples)1543 bool CSG_Grids::Set_Max_Samples(sLong Max_Samples)
1544 {
1545 	if( CSG_Data_Object::Set_Max_Samples(Max_Samples) )
1546 	{
1547 		for(int i=0; i<Get_Grid_Count(); i++)
1548 		{
1549 			Get_Grid_Ptr(i)->Set_Max_Samples(Max_Samples);
1550 		}
1551 
1552 		return( true );
1553 	}
1554 
1555 	return( false );
1556 }
1557 
1558 //---------------------------------------------------------
1559 #define SG_GRID_HISTOGRAM_CLASSES_DEFAULT	255
1560 
1561 //---------------------------------------------------------
1562 /**
1563 * Returns the histogram for the whole data set. It is
1564 * automatically updated if necessary.
1565 */
Get_Histogram(size_t nClasses)1566 const CSG_Histogram & CSG_Grids::Get_Histogram(size_t nClasses)
1567 {
1568 	Update();
1569 
1570 	if( nClasses > 1 && nClasses != m_Histogram.Get_Class_Count() )
1571 	{
1572 		m_Histogram.Destroy();
1573 	}
1574 
1575 	if( m_Histogram.Get_Statistics().Get_Count() < 1 )
1576 	{
1577 		m_Histogram.Create(nClasses > 1 ? nClasses : SG_GRID_HISTOGRAM_CLASSES_DEFAULT, Get_Min(), Get_Max(), this, (size_t)Get_Max_Samples());
1578 	}
1579 
1580 	return( m_Histogram );
1581 }
1582 
1583 //---------------------------------------------------------
Get_Histogram(const CSG_Rect & rWorld,CSG_Histogram & Histogram,size_t nClasses) const1584 bool CSG_Grids::Get_Histogram(const CSG_Rect &rWorld, CSG_Histogram &Histogram, size_t nClasses)	const
1585 {
1586 	CSG_Simple_Statistics	Statistics;
1587 
1588 	if( !Get_Statistics(rWorld, Statistics) )
1589 	{
1590 		return( false );
1591 	}
1592 
1593 	int	xMin	= Get_System().Get_xWorld_to_Grid(rWorld.Get_XMin()); if( xMin <  0        ) xMin = 0;
1594 	int	yMin	= Get_System().Get_yWorld_to_Grid(rWorld.Get_YMin()); if( yMin <  0        ) yMin = 0;
1595 	int	xMax	= Get_System().Get_xWorld_to_Grid(rWorld.Get_XMax()); if( xMax >= Get_NX() ) xMax = Get_NX() - 1;
1596 	int	yMax	= Get_System().Get_yWorld_to_Grid(rWorld.Get_YMax()); if( yMax >= Get_NY() ) yMax = Get_NY() - 1;
1597 
1598 	if( xMin > xMax || yMin > yMax )
1599 	{
1600 		return( false );	// no overlap
1601 	}
1602 
1603 	Histogram.Create(nClasses > 1 ? nClasses : SG_GRID_HISTOGRAM_CLASSES_DEFAULT, Statistics.Get_Minimum(), Statistics.Get_Maximum());
1604 
1605 	int		nx		= 1 + (xMax - xMin);
1606 	int		ny		= 1 + (yMax - yMin);
1607 	sLong	nCells	= nx * ny;
1608 
1609 	double	Offset = Get_Offset(), Scaling = is_Scaled() ? Get_Scaling() : 0.;
1610 
1611 	if( Get_Max_Samples() > 0 && Get_Max_Samples() < nCells )
1612 	{
1613 		double	d = (double)nCells / (double)Get_Max_Samples();
1614 
1615 		for(double i=0; i<(double)nCells; i+=d)
1616 		{
1617 			int	y	= yMin + (int)i / nx;
1618 			int	x	= xMin + (int)i % nx;
1619 
1620 			for(int z=0; z<Get_NZ(); z++)
1621 			{
1622 				double	Value	= asDouble(x, y, z, false);
1623 
1624 				if( !is_NoData_Value(Value) )
1625 				{
1626 					Histogram	+= Scaling ? Offset + Scaling * Value : Value;
1627 				}
1628 			}
1629 		}
1630 	}
1631 	else
1632 	{
1633 		for(int x=xMin; x<=xMax; x++)
1634 		{
1635 			for(int y=yMin; y<=yMax; y++)
1636 			{
1637 				for(int z=0; z<Get_NZ(); z++)
1638 				{
1639 					double	Value	= asDouble(x, y, z, false);
1640 
1641 					if( !is_NoData_Value(Value) )
1642 					{
1643 						Histogram	+= Scaling ? Offset + Scaling * Value : Value;
1644 					}
1645 				}
1646 			}
1647 		}
1648 	}
1649 
1650 	return( Histogram.Update() );
1651 }
1652 
1653 
1654 ///////////////////////////////////////////////////////////
1655 //														 //
1656 //														 //
1657 //														 //
1658 ///////////////////////////////////////////////////////////
1659 
1660 //---------------------------------------------------------
On_Reload(void)1661 bool CSG_Grids::On_Reload(void)
1662 {
1663 	return( Create(Get_File_Name(false)) );
1664 }
1665 
1666 //---------------------------------------------------------
On_Delete(void)1667 bool CSG_Grids::On_Delete(void)
1668 {
1669 	CSG_String	FileName	= Get_File_Name(true);
1670 
1671 	SG_File_Set_Extension(FileName, "sg-gds-z"); SG_File_Delete(FileName);
1672 	SG_File_Set_Extension(FileName, "sg-gds"  ); SG_File_Delete(FileName);
1673 	SG_File_Set_Extension(FileName, "sg-info" ); SG_File_Delete(FileName);
1674 	SG_File_Set_Extension(FileName, "sg-prj"  ); SG_File_Delete(FileName);
1675 
1676 	int	i	= 0;
1677 
1678 	do
1679 	{
1680 		SG_File_Set_Extension(FileName, CSG_String::Format("sg-%03d", ++i));
1681 	}
1682 	while( SG_File_Delete(FileName) );
1683 
1684 	return( true );
1685 }
1686 
1687 
1688 ///////////////////////////////////////////////////////////
1689 //														 //
1690 ///////////////////////////////////////////////////////////
1691 
1692 //---------------------------------------------------------
Load(const CSG_String & FileName,bool bLoadData)1693 bool CSG_Grids::Load(const CSG_String &FileName, bool bLoadData)
1694 {
1695 	Destroy();
1696 
1697 	SG_UI_Msg_Add(CSG_String::Format("%s: %s...", _TL("Loading grid collection"), FileName.c_str()), true);
1698 
1699 	if( _Load_PGSQL     (FileName)
1700 	||  _Load_Normal    (FileName)
1701 	||  _Load_Compressed(FileName)
1702 	||  _Load_External  (FileName) )
1703 	{
1704 		Set_Modified(false);
1705 
1706 		Set_Name(SG_File_Get_Name(FileName, false));
1707 
1708 		SG_UI_Process_Set_Ready();
1709 		SG_UI_Msg_Add(_TL("okay"), false, SG_UI_MSG_STYLE_SUCCESS);
1710 
1711 		return( true );
1712 	}
1713 
1714 	SG_UI_Process_Set_Ready();
1715 	SG_UI_Msg_Add(_TL("failed"), false, SG_UI_MSG_STYLE_FAILURE);
1716 
1717 	return( false );
1718 }
1719 
1720 //---------------------------------------------------------
Save(const CSG_String & FileName,int Format)1721 bool CSG_Grids::Save(const CSG_String &FileName, int Format)
1722 {
1723 	SG_UI_Msg_Add(CSG_String::Format("%s %s: %s...", _TL("Saving"), _TL("grid collection"), FileName.c_str()), true);
1724 
1725 	if( Format == GRIDS_FILE_FORMAT_Undefined )
1726 	{
1727 		Format	= GRIDS_FILE_FORMAT_Compressed;	// default
1728 
1729 		if( SG_File_Cmp_Extension(FileName, "sg-gds"  ) )	Format	= GRIDS_FILE_FORMAT_Normal    ;
1730 		if( SG_File_Cmp_Extension(FileName, "sg-gds-z") )	Format	= GRIDS_FILE_FORMAT_Compressed;
1731 		if( SG_File_Cmp_Extension(FileName, "tif"     ) )	Format	= GRIDS_FILE_FORMAT_GeoTIFF   ;
1732 	}
1733 
1734 	bool	bResult	= false;
1735 
1736 	switch( Format )
1737 	{
1738 	case GRIDS_FILE_FORMAT_Normal    :
1739 		bResult = _Save_Normal    (FileName);
1740 		break;
1741 
1742 	case GRIDS_FILE_FORMAT_Compressed: default:
1743 		bResult = _Save_Compressed(FileName);
1744 		break;
1745 
1746 	case GRIDS_FILE_FORMAT_GeoTIFF   :
1747 		SG_RUN_TOOL(bResult, "io_gdal", 2,	// Export GeoTIFF
1748 			SG_TOOL_PARAMLIST_ADD("GRIDS", this)
1749 		&&	SG_TOOL_PARAMETER_SET("FILE" , FileName)
1750 		);
1751 		break;
1752 	}
1753 
1754 	//-----------------------------------------------------
1755 	SG_UI_Process_Set_Ready();
1756 
1757 	if( bResult )
1758 	{
1759 		Set_Modified(false);
1760 
1761 		Set_File_Name(FileName, true);
1762 
1763 		SG_UI_Msg_Add(_TL("okay"), false, SG_UI_MSG_STYLE_SUCCESS);
1764 
1765 		return( true );
1766 	}
1767 
1768 	SG_UI_Msg_Add(_TL("failed"), false, SG_UI_MSG_STYLE_FAILURE);
1769 
1770 	return( false );
1771 }
1772 
1773 
1774 ///////////////////////////////////////////////////////////
1775 //														 //
1776 ///////////////////////////////////////////////////////////
1777 
1778 //---------------------------------------------------------
_Load_External(const CSG_String & FileName)1779 bool CSG_Grids::_Load_External(const CSG_String &FileName)
1780 {
1781 	bool	bResult	= false;
1782 
1783 	CSG_Data_Manager	Data;
1784 
1785 	CSG_Tool	*pTool	= SG_Get_Tool_Library_Manager().Create_Tool("io_gdal", 0);	// import raster
1786 
1787 	SG_UI_Msg_Lock(true);
1788 
1789 	if(	pTool && pTool->On_Before_Execution() && pTool->Settings_Push(&Data)
1790 	&&  pTool->Set_Parameter("FILES"   , FileName)
1791 	&&	pTool->Set_Parameter("MULTIPLE", 1       )	// output as grid collection
1792 	&&	pTool->Execute()
1793 	&&  Data.Grid_System_Count() > 0 && Data.Get_Grid_System(0)->Count() > 0 && Data.Get_Grid_System(0)->Get(0)->is_Valid() )
1794 	{
1795 		CSG_Grids	*pGrids	= (CSG_Grids *)Data.Get_Grid_System(0)->Get(0);
1796 
1797 		for(int i=0; i<pGrids->Get_Grid_Count(); i++)
1798 		{
1799 			Add_Grid(pGrids->Get_Z(i), pGrids->Get_Grid_Ptr(i), true);
1800 		}
1801 
1802 		pGrids->Del_Grids(true);
1803 
1804 		Set_File_Name(FileName, false);
1805 
1806 		Set_Name       (pGrids->Get_Name       ());
1807 		Set_Description(pGrids->Get_Description());
1808 
1809 		bResult	= true;
1810 	}
1811 
1812 	SG_UI_Msg_Lock(false);
1813 
1814 	SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
1815 
1816 	return( bResult );
1817 }
1818 
1819 //---------------------------------------------------------
_Load_PGSQL(const CSG_String & FileName)1820 bool CSG_Grids::_Load_PGSQL(const CSG_String &FileName)
1821 {
1822 	bool	bResult	= false;
1823 
1824 	if( FileName.BeforeFirst(':').Cmp("PGSQL") == 0 )	// database source
1825 	{
1826 		CSG_String	s(FileName);
1827 
1828 		s	= s.AfterFirst(':');	CSG_String	Host  (s.BeforeFirst(':'));
1829 		s	= s.AfterFirst(':');	CSG_String	Port  (s.BeforeFirst(':'));
1830 		s	= s.AfterFirst(':');	CSG_String	DBName(s.BeforeFirst(':'));
1831 		s	= s.AfterFirst(':');	CSG_String	Table (s.BeforeFirst(':'));
1832 		s	= s.AfterFirst(':');	CSG_String	rid   (s.BeforeFirst(':').AfterFirst('='));
1833 
1834 		//-------------------------------------------------
1835 		CSG_String_Tokenizer	rids(rid, ",");	rid.Clear();
1836 
1837 		while( rids.Has_More_Tokens() )
1838 		{
1839 			if( !rid.is_Empty() )
1840 			{
1841 				rid	+= " OR ";
1842 			}
1843 
1844 			rid	+= "rid=\'" + rids.Get_Next_Token() + "\'";
1845 		}
1846 
1847 		//-------------------------------------------------
1848 		CSG_Tool	*pTool	= SG_Get_Tool_Library_Manager().Create_Tool("db_pgsql", 0, true);	// CGet_Connections
1849 
1850 		if(	pTool != NULL )
1851 		{
1852 			SG_UI_ProgressAndMsg_Lock(true);
1853 
1854 			//---------------------------------------------
1855 			CSG_Table	Connections;
1856 			CSG_String	Connection	= DBName + " [" + Host + ":" + Port + "]";
1857 
1858 			pTool->Set_Manager(NULL);
1859 			pTool->On_Before_Execution();
1860 
1861 			if( SG_TOOL_PARAMETER_SET("CONNECTIONS", &Connections) && pTool->Execute() )	// CGet_Connections
1862 			{
1863 				for(int i=0; !bResult && i<Connections.Get_Count(); i++)
1864 				{
1865 					if( !Connection.Cmp(Connections[i].asString(0)) )
1866 					{
1867 						bResult	= true;
1868 					}
1869 				}
1870 			}
1871 
1872 			SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
1873 
1874 			//---------------------------------------------
1875 			if( bResult && (bResult = (pTool = SG_Get_Tool_Library_Manager().Create_Tool("db_pgsql", 30, true)) != NULL) == true )	// CPGIS_Raster_Load
1876 			{
1877 				CSG_Data_Manager	Grids;
1878 
1879 				pTool->On_Before_Execution();
1880 				pTool->Settings_Push(&Grids);
1881 
1882 				bResult	=  SG_TOOL_PARAMETER_SET("CONNECTION", Connection)
1883 						&& SG_TOOL_PARAMETER_SET("TABLES"    , Table)
1884 						&& SG_TOOL_PARAMETER_SET("MULTIPLE"  , 1)	// grid collection
1885 						&& SG_TOOL_PARAMETER_SET("WHERE"     , rid)
1886 						&& pTool->Execute();
1887 
1888 				SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
1889 
1890 				//-----------------------------------------
1891 				if( Grids.Grid_System_Count() > 0 && Grids.Get_Grid_System(0)->Get(0) && Grids.Get_Grid_System(0)->Get(0)->is_Valid() )
1892 				{
1893 					CSG_Grids	*pGrids	= (CSG_Grids *)Grids.Get_Grid_System(0)->Get(0);
1894 
1895 					Set_File_Name(FileName);
1896 
1897 					Create(pGrids);
1898 
1899 					for(int i=0; i<pGrids->Get_Grid_Count(); i++)
1900 					{
1901 						Add_Grid(pGrids->Get_Attributes(i), pGrids->Get_Grid_Ptr(i), true);
1902 					}
1903 
1904 					pGrids->Del_Grids(true);
1905 				}
1906 			}
1907 
1908 			SG_UI_ProgressAndMsg_Lock(false);
1909 		}
1910 	}
1911 
1912 	return( Get_NZ() > 0 );
1913 }
1914 
1915 
1916 ///////////////////////////////////////////////////////////
1917 //														 //
1918 ///////////////////////////////////////////////////////////
1919 
1920 //---------------------------------------------------------
_Load_Normal(const CSG_String & _FileName)1921 bool CSG_Grids::_Load_Normal(const CSG_String &_FileName)
1922 {
1923 	if( !SG_File_Cmp_Extension(_FileName, "sg-gds") ) // GRIDS_FILETYPE_Normal
1924 	{
1925 		return( false );
1926 	}
1927 
1928 	CSG_String	FileName(_FileName);
1929 
1930 	CSG_File	Stream;
1931 
1932 	//-----------------------------------------------------
1933 	if( !Stream.Open(FileName, SG_FILE_R, false) || !_Load_Header(Stream) )
1934 	{
1935 		return( false );
1936 	}
1937 
1938 	SG_File_Set_Extension(FileName, "sg-att");
1939 
1940 	if( m_Attributes.Get_Count() <= 0 )	// <<< DEPRECATED
1941 	if( !Stream.Open(FileName, SG_FILE_R, false) || !_Load_Attributes(Stream) )
1942 	{
1943 		return( false );
1944 	}
1945 
1946 	//-----------------------------------------------------
1947 	for(int i=0; i<Get_NZ() && SG_UI_Process_Set_Progress(i, Get_NZ()); i++)
1948 	{
1949 		SG_File_Set_Extension(FileName, CSG_String::Format("sg-%03d", i + 1));
1950 
1951 		if( !Stream.Open(FileName, SG_FILE_R, true) || !_Load_Data(Stream, m_pGrids[i]) )
1952 		{
1953 			return( false );
1954 		}
1955 	}
1956 
1957 	//-----------------------------------------------------
1958 	Set_File_Name(_FileName, true);
1959 
1960 	Load_MetaData(FileName);
1961 
1962 	Get_Projection().Load(SG_File_Make_Path("", FileName, "sg-prj"), SG_PROJ_FMT_WKT);
1963 
1964 	return( true );
1965 }
1966 
1967 //---------------------------------------------------------
_Save_Normal(const CSG_String & _FileName)1968 bool CSG_Grids::_Save_Normal(const CSG_String &_FileName)
1969 {
1970 	CSG_String	FileName(_FileName);
1971 
1972 	CSG_File	Stream;
1973 
1974 	//-----------------------------------------------------
1975 	SG_File_Set_Extension(FileName, "sg-gds");
1976 
1977 	if( !Stream.Open(FileName, SG_FILE_W, false) || !_Save_Header(Stream) )
1978 	{
1979 		return( false );
1980 	}
1981 
1982 	SG_File_Set_Extension(FileName, "sg-att");
1983 
1984 	if( !Stream.Open(FileName, SG_FILE_W, false) || !_Save_Attributes(Stream) )
1985 	{
1986 		return( false );
1987 	}
1988 
1989 	//-----------------------------------------------------
1990 	for(int i=0; i<Get_NZ() && SG_UI_Process_Set_Progress(i, Get_NZ()); i++)
1991 	{
1992 		SG_File_Set_Extension(FileName, CSG_String::Format("sg-%03d", i + 1));
1993 
1994 		if( !Stream.Open(FileName, SG_FILE_W, true) || !_Save_Data(Stream, m_pGrids[i]) )
1995 		{
1996 			return( false );
1997 		}
1998 	}
1999 
2000 	//-----------------------------------------------------
2001 	Save_MetaData(FileName);
2002 
2003 	Get_Projection().Save(SG_File_Make_Path("", FileName, "sg-prj"), SG_PROJ_FMT_WKT);
2004 
2005 	return( true );
2006 }
2007 
2008 
2009 ///////////////////////////////////////////////////////////
2010 //														 //
2011 ///////////////////////////////////////////////////////////
2012 
2013 //---------------------------------------------------------
_Load_Compressed(const CSG_String & _FileName)2014 bool CSG_Grids::_Load_Compressed(const CSG_String &_FileName)
2015 {
2016 	if( !SG_File_Cmp_Extension(_FileName, "sg-gds-z") ) // GRIDS_FILETYPE_Compressed
2017 	{
2018 		return( false );
2019 	}
2020 
2021 	CSG_File_Zip	Stream(_FileName, SG_FILE_R);
2022 
2023 	CSG_String	FileName(SG_File_Get_Name(_FileName, false) + ".");
2024 
2025 	//-----------------------------------------------------
2026 	if( !Stream.Get_File(FileName + "sg-gds") || !_Load_Header(Stream) )
2027 	{
2028 		return( false );
2029 	}
2030 
2031 	if( m_Attributes.Get_Count() <= 0 )	// <<< DEPRECATED
2032 	if( !Stream.Get_File(FileName + "sg-att") || !_Load_Attributes(Stream) )
2033 	{
2034 		return( false );
2035 	}
2036 
2037 	//-----------------------------------------------------
2038 	for(int i=0; i<Get_NZ() && SG_UI_Process_Set_Progress(i, Get_NZ()); i++)
2039 	{
2040 		if( !Stream.Get_File(FileName + CSG_String::Format("sg-%03d", i + 1)) || !_Load_Data(Stream, m_pGrids[i]) )
2041 		{
2042 			return( false );
2043 		}
2044 	}
2045 
2046 	//-----------------------------------------------------
2047 	Set_File_Name(_FileName, true);
2048 
2049 	if( Stream.Get_File(FileName + "sg-info") )
2050 	{
2051 		Load_MetaData(Stream);
2052 	}
2053 
2054 	if( Stream.Get_File(FileName + "sg-prj") )
2055 	{
2056 		Get_Projection().Load(Stream, SG_PROJ_FMT_WKT);
2057 	}
2058 
2059 	return( true );
2060 }
2061 
2062 //---------------------------------------------------------
_Save_Compressed(const CSG_String & _FileName)2063 bool CSG_Grids::_Save_Compressed(const CSG_String &_FileName)
2064 {
2065 	CSG_File_Zip	Stream(_FileName, SG_FILE_W);
2066 
2067 	CSG_String	FileName(SG_File_Get_Name(_FileName, false) + ".");
2068 
2069 	//-----------------------------------------------------
2070 	if( !Stream.Add_File(FileName + "sg-gds") || !_Save_Header(Stream) )
2071 	{
2072 		return( false );
2073 	}
2074 
2075 	if( !Stream.Add_File(FileName + "sg-att") || !_Save_Attributes(Stream) )
2076 	{
2077 		return( false );
2078 	}
2079 
2080 	//-----------------------------------------------------
2081 	for(int i=0; i<Get_NZ() && SG_UI_Process_Set_Progress(i, Get_NZ()); i++)
2082 	{
2083 		if( !Stream.Add_File(FileName + CSG_String::Format("sg-%03d", i + 1)) || !_Save_Data(Stream, m_pGrids[i]) )
2084 		{
2085 			return( false );
2086 		}
2087 	}
2088 
2089 	//-----------------------------------------------------
2090 	if( Stream.Add_File(FileName + "sg-info") )
2091 	{
2092 		Save_MetaData(Stream);
2093 	}
2094 
2095 	if( Stream.Add_File(FileName + "sg-prj") )
2096 	{
2097 		Get_Projection().Save(Stream, SG_PROJ_FMT_WKT);
2098 	}
2099 
2100 	return( true );
2101 }
2102 
2103 
2104 ///////////////////////////////////////////////////////////
2105 //														 //
2106 ///////////////////////////////////////////////////////////
2107 
2108 //---------------------------------------------------------
_Load_Header(CSG_File & Stream)2109 bool CSG_Grids::_Load_Header(CSG_File &Stream)
2110 {
2111 	CSG_MetaData	Header;
2112 
2113 	if( !Header.Load(Stream) )
2114 	{
2115 		return( false );
2116 	}
2117 
2118 	//-----------------------------------------------------
2119 	if( !Header("NX") || !Header("NY") || !Header("XMIN") || !Header("YMIN") || !Header("CELLSIZE") || !Header("TYPE") )	// necessary minimum information !!!
2120 	{
2121 		return( false );
2122 	}
2123 
2124 	CSG_Grid_System	System(Header["CELLSIZE"].Get_Content().asDouble(),
2125 		Header["XMIN"].Get_Content().asDouble(), Header["YMIN"].Get_Content().asDouble(),
2126 		Header["NX"  ].Get_Content().asInt   (), Header["NY"  ].Get_Content().asInt   ()
2127 	);
2128 
2129 	TSG_Data_Type	Type	= SG_Data_Type_Get_Type(Header["TYPE"].Get_Content());
2130 
2131 	if( !System.is_Valid() || Type == SG_DATATYPE_Undefined || !m_pGrids[0]->Create(System, Type) )
2132 	{
2133 		return( false );
2134 	}
2135 
2136 	//-----------------------------------------------------
2137 	if( Header("NAME"       ) ) Set_Name       (Header["NAME"       ].Get_Content());
2138 	if( Header("DESCRIPTION") ) Set_Description(Header["DESCRIPTION"].Get_Content());
2139 	if( Header("UNIT"       ) ) Set_Unit       (Header["UNIT"       ].Get_Content());
2140 
2141 	Set_Scaling(
2142 		Header("SCALE" ) ? Header["SCALE" ].Get_Content().asDouble() : 1.,
2143 		Header("OFFSET") ? Header["OFFSET"].Get_Content().asDouble() : 0.
2144 	);
2145 
2146 	if( Header("NODATA_MIN") )
2147 	{
2148 		if( Header("NODATA_MAX") )
2149 		{
2150 			Set_NoData_Value_Range(
2151 				Header["NODATA_MIN"].Get_Content().asDouble(),
2152 				Header["NODATA_MAX"].Get_Content().asDouble()
2153 			);
2154 		}
2155 		else
2156 		{
2157 			Set_NoData_Value(
2158 				Header["NODATA_MIN"].Get_Content().asDouble()
2159 			);
2160 		}
2161 	}
2162 
2163 	//-----------------------------------------------------
2164 	m_Attributes.Destroy();
2165 
2166 	if( Header("ATTRIBUTES") && Header["ATTRIBUTES"]("FIELDS") == NULL )
2167 	{
2168 		const CSG_MetaData	&Fields	= Header["ATTRIBUTES"];
2169 
2170 		for(int iField=0; iField<Fields.Get_Children_Count(); iField++)
2171 		{
2172 			if( Fields[iField].Cmp_Name("FIELD") && Fields[iField].Get_Property("TYPE") )
2173 			{
2174 				m_Attributes.Add_Field(Fields[iField].Get_Content(), SG_Data_Type_Get_Type(Fields[iField].Get_Property("TYPE")));
2175 			}
2176 		}
2177 
2178 		if( !Fields.Get_Property("Z_FIELD", m_Z_Attribute) || m_Z_Attribute >= m_Attributes.Get_Field_Count() )
2179 		{
2180 			m_Z_Attribute	= 0;
2181 		}
2182 
2183 		if( !Fields.Get_Property("Z_NAME", m_Z_Name      ) || m_Z_Name      >= m_Attributes.Get_Field_Count() )
2184 		{
2185 			m_Z_Name	= -1;	// same as m_Z_Attribute
2186 		}
2187 	}
2188 
2189 	//-----------------------------------------------------
2190 	// >>> DEPRECATED >>> //
2191 	if( Header("ATTRIBUTES") && Header["ATTRIBUTES"]("FIELDS") != NULL )
2192 	{
2193 		if( !Header["ATTRIBUTES"].Get_Property("ZATTRIBUTE", m_Z_Attribute) )
2194 		{
2195 			m_Z_Attribute	= 0;
2196 		}
2197 
2198 		int		iField;
2199 
2200 		const CSG_MetaData	&Fields	= Header["ATTRIBUTES"]["FIELDS"];
2201 
2202 		for(iField=0; iField<Fields.Get_Children_Count(); iField++)
2203 		{
2204 			if( Fields[iField].Cmp_Name("FIELD") && Fields[iField].Get_Property("TYPE") )
2205 			{
2206 				m_Attributes.Add_Field(Fields[iField].Get_Content(), SG_Data_Type_Get_Type(Fields[iField].Get_Property("TYPE")));
2207 			}
2208 		}
2209 
2210 		if( m_Attributes.Get_Field_Count() > 0 && Header["ATTRIBUTES"]("RECORDS") )
2211 		{
2212 			CSG_Table	Attributes(m_Attributes);
2213 
2214 			const CSG_MetaData	&Records	= Header["ATTRIBUTES"]["RECORDS"];
2215 
2216 			for(int iRecord=0; iRecord<Records.Get_Children_Count(); iRecord++)
2217 			{
2218 				if( Records[iRecord].Cmp_Name("RECORD") )
2219 				{
2220 					CSG_String_Tokenizer	Values(Records[iRecord].Get_Content(), ";");
2221 
2222 					if( Values.Get_Tokens_Count() == (size_t)Attributes.Get_Field_Count() )
2223 					{
2224 						CSG_Table_Record	*pRecord	= Attributes.Add_Record();
2225 
2226 						for(int iField=0; iField<m_Attributes.Get_Field_Count(); iField++)
2227 						{
2228 							pRecord->Set_Value(iField, Values.Get_Next_Token());
2229 						}
2230 
2231 						if( !Add_Grid(*pRecord) )
2232 						{
2233 							return( false );
2234 						}
2235 					}
2236 				}
2237 			}
2238 		}
2239 	}
2240 	else if( Header("NZ") && Header["NZ"].Get_Content().asInt() > 0 )
2241 	{
2242 		m_Attributes.Add_Field("ID", SG_DATATYPE_Int);
2243 
2244 		for(int i=0, n=Header["NZ"].Get_Content().asInt(); i<n; i++)
2245 		{
2246 			if( !Add_Grid(i + 1.) )
2247 			{
2248 				return( false );
2249 			}
2250 		}
2251 	}
2252 	// <<< DEPRECATED <<< //
2253 
2254 	//-----------------------------------------------------
2255 	return( m_Attributes.Get_Field_Count() > 0 );
2256 }
2257 
2258 //---------------------------------------------------------
_Save_Header(CSG_File & Stream)2259 bool CSG_Grids::_Save_Header(CSG_File &Stream)
2260 {
2261 	CSG_MetaData	Header;
2262 
2263 	Header.Set_Name("GRIDS");
2264 
2265 	Header.Add_Property("saga-version", SAGA_VERSION);
2266 
2267 	//-----------------------------------------------------
2268 	// general
2269 
2270 	Header.Add_Child("NAME"       , Get_Name       ());
2271 	Header.Add_Child("DESCRIPTION", Get_Description());
2272 	Header.Add_Child("UNIT"       , Get_Unit       ());
2273 
2274 	Header.Add_Child("SCALE"      , Get_Scaling    ());
2275 	Header.Add_Child("OFFSET"     , Get_Offset     ());
2276 
2277 	Header.Add_Child("NODATA_MIN" , Get_NoData_Value(false));
2278 	Header.Add_Child("NODATA_MAX" , Get_NoData_Value(true ));
2279 
2280 	Header.Add_Child("TYPE"       , SG_Data_Type_Get_Identifier(Get_Type()));
2281 
2282 	//-----------------------------------------------------
2283 	// grid system
2284 
2285 	Header.Add_Child("NX"         , Get_NX      ());
2286 	Header.Add_Child("NY"         , Get_NY      ());
2287 	Header.Add_Child("CELLSIZE"   , Get_Cellsize());
2288 	Header.Add_Child("XMIN"       , Get_XMin    ());
2289 	Header.Add_Child("YMIN"       , Get_YMin    ());
2290 
2291 	//-----------------------------------------------------
2292 	// attributes
2293 
2294 	CSG_MetaData	&Attributes	= *Header.Add_Child("ATTRIBUTES");
2295 
2296 	Attributes.Add_Property("Z_FIELD", m_Z_Attribute);
2297 	Attributes.Add_Property("Z_NAME" , m_Z_Name     );
2298 
2299 	for(int iField=0; iField<m_Attributes.Get_Field_Count(); iField++)
2300 	{
2301 		Attributes.Add_Child("FIELD", m_Attributes.Get_Field_Name(iField))->Add_Property(
2302 			"TYPE", SG_Data_Type_Get_Identifier(m_Attributes.Get_Field_Type(iField))
2303 		);
2304 	}
2305 
2306 	//-----------------------------------------------------
2307 	return( Header.Save(Stream) );
2308 }
2309 
2310 
2311 ///////////////////////////////////////////////////////////
2312 //														 //
2313 ///////////////////////////////////////////////////////////
2314 
2315 //---------------------------------------------------------
_Load_Attributes(CSG_File & Stream)2316 bool CSG_Grids::_Load_Attributes(CSG_File &Stream)
2317 {
2318 	CSG_Table	Attributes(m_Attributes);
2319 
2320 	CSG_String	sLine;
2321 
2322 	while( Stream.Read_Line(sLine) && !sLine.is_Empty() )
2323 	{
2324 		CSG_String_Tokenizer	Values(sLine, "\t", SG_TOKEN_RET_EMPTY_ALL);
2325 
2326 		if( Values.Get_Tokens_Count() == (size_t)Attributes.Get_Field_Count() )
2327 		{
2328 			CSG_Table_Record	*pRecord	= Attributes.Add_Record();
2329 
2330 			for(int iField=0; iField<m_Attributes.Get_Field_Count(); iField++)
2331 			{
2332 				pRecord->Set_Value(iField, Values.Get_Next_Token());
2333 			}
2334 
2335 			if( !Add_Grid(*pRecord) )
2336 			{
2337 				return( false );
2338 			}
2339 		}
2340 	}
2341 
2342 	return( true );
2343 }
2344 
2345 //---------------------------------------------------------
_Save_Attributes(CSG_File & Stream)2346 bool CSG_Grids::_Save_Attributes(CSG_File &Stream)
2347 {
2348 	for(int iRecord=0; iRecord<m_Attributes.Get_Count(); iRecord++)
2349 	{
2350 		for(int iField=0; iField<m_Attributes.Get_Field_Count(); iField++)
2351 		{
2352 			Stream.Write(m_Attributes[iRecord].asString(iField));
2353 			Stream.Write(iField < m_Attributes.Get_Field_Count() - 1 ? "\t" : "\n");
2354 		}
2355 	}
2356 
2357 	return( true );
2358 }
2359 
2360 
2361 ///////////////////////////////////////////////////////////
2362 //														 //
2363 ///////////////////////////////////////////////////////////
2364 
2365 //---------------------------------------------------------
_Load_Data(CSG_File & Stream,CSG_Grid * pGrid)2366 bool CSG_Grids::_Load_Data(CSG_File &Stream, CSG_Grid *pGrid)
2367 {
2368 	if( !pGrid )
2369 	{
2370 		return( false );
2371 	}
2372 
2373 	TSG_Data_Type	Type	= Get_Type();
2374 
2375 	CSG_Array	Line(1, Get_nLineBytes());
2376 
2377 	for(int y=0; y<Get_NY(); y++)
2378 	{
2379 		if( !Stream.Read(Line.Get_Array(), Get_nLineBytes()) )
2380 		{
2381 			return( false );
2382 		}
2383 
2384 		char	*pValue	= (char *)Line.Get_Array();
2385 
2386 		for(int x=0, n=Get_nValueBytes(); x<Get_NX(); x++, pValue+=n)
2387 		{
2388 			switch( Type )
2389 			{
2390 			case SG_DATATYPE_Byte  : pGrid->Set_Value(x, y, *(BYTE   *)pValue, false);	break;
2391 			case SG_DATATYPE_Char  : pGrid->Set_Value(x, y, *(char   *)pValue, false);	break;
2392 			case SG_DATATYPE_Word  : pGrid->Set_Value(x, y, *(WORD   *)pValue, false);	break;
2393 			case SG_DATATYPE_Short : pGrid->Set_Value(x, y, *(short  *)pValue, false);	break;
2394 			case SG_DATATYPE_DWord : pGrid->Set_Value(x, y, *(DWORD  *)pValue, false);	break;
2395 			case SG_DATATYPE_Int   : pGrid->Set_Value(x, y, *(int    *)pValue, false);	break;
2396 			case SG_DATATYPE_Float : pGrid->Set_Value(x, y, *(float  *)pValue, false);	break;
2397 			case SG_DATATYPE_Double: pGrid->Set_Value(x, y, *(double *)pValue, false);	break;
2398 			default:	break;
2399 			}
2400 		}
2401 	}
2402 
2403 	return( true );
2404 }
2405 
2406 //---------------------------------------------------------
_Save_Data(CSG_File & Stream,CSG_Grid * pGrid)2407 bool CSG_Grids::_Save_Data(CSG_File &Stream, CSG_Grid *pGrid)
2408 {
2409 	TSG_Data_Type	Type	= Get_Type();
2410 
2411 	CSG_Array	Line(1, Get_nLineBytes());
2412 
2413 	for(int y=0; y<Get_NY(); y++)
2414 	{
2415 		char	*pValue	= (char *)Line.Get_Array();
2416 
2417 		for(int x=0, n=Get_nValueBytes(); x<Get_NX(); x++, pValue+=n)
2418 		{
2419 			switch( Type )
2420 			{
2421 			case SG_DATATYPE_Byte  : *(BYTE   *)pValue	= pGrid->asByte  (x, y, false);	break;
2422 			case SG_DATATYPE_Char  : *(char   *)pValue	= pGrid->asChar  (x, y, false);	break;
2423 			case SG_DATATYPE_Word  : *(WORD   *)pValue	= pGrid->asShort (x, y, false);	break;
2424 			case SG_DATATYPE_Short : *(short  *)pValue	= pGrid->asShort (x, y, false);	break;
2425 			case SG_DATATYPE_DWord : *(DWORD  *)pValue	= pGrid->asInt   (x, y, false);	break;
2426 			case SG_DATATYPE_Int   : *(int    *)pValue	= pGrid->asInt   (x, y, false);	break;
2427 			case SG_DATATYPE_Float : *(float  *)pValue	= pGrid->asFloat (x, y, false);	break;
2428 			case SG_DATATYPE_Double: *(double *)pValue	= pGrid->asDouble(x, y, false);	break;
2429 			default:	break;
2430 			}
2431 		}
2432 
2433 		if( !Stream.Write(Line.Get_Array(), Get_nLineBytes()) )
2434 		{
2435 			return( false );
2436 		}
2437 	}
2438 
2439 	return( true );
2440 }
2441 
2442 
2443 ///////////////////////////////////////////////////////////
2444 //														 //
2445 ///////////////////////////////////////////////////////////
2446 
2447 //-----------------------------------------------------
_Assign_Interpolated(CSG_Grids * pSource,TSG_Grid_Resampling Interpolation)2448 bool CSG_Grids::_Assign_Interpolated	(CSG_Grids *pSource, TSG_Grid_Resampling Interpolation)	{	return( false );	}
_Assign_MeanValue(CSG_Grids * pSource,bool bVolumeProportional)2449 bool CSG_Grids::_Assign_MeanValue		(CSG_Grids *pSource, bool bVolumeProportional         )	{	return( false );	}
_Assign_ExtremeValue(CSG_Grids * pSource,bool bMaximum)2450 bool CSG_Grids::_Assign_ExtremeValue	(CSG_Grids *pSource, bool bMaximum                    )	{	return( false );	}
_Assign_Majority(CSG_Grids * pSource)2451 bool CSG_Grids::_Assign_Majority		(CSG_Grids *pSource                                   )	{	return( false );	}
2452 
2453 
2454 ///////////////////////////////////////////////////////////
2455 //														 //
2456 ///////////////////////////////////////////////////////////
2457 
2458 //-----------------------------------------------------
_Operation_Arithmetic(const CSG_Grids & Grids,TSG_Grid_Operation Operation)2459 CSG_Grids & CSG_Grids::_Operation_Arithmetic(const CSG_Grids &Grids, TSG_Grid_Operation Operation)	{	return( *this );	}
_Operation_Arithmetic(double Value,TSG_Grid_Operation Operation)2460 CSG_Grids & CSG_Grids::_Operation_Arithmetic(double Value          , TSG_Grid_Operation Operation)	{	return( *this );	}
2461 
2462 
2463 ///////////////////////////////////////////////////////////
2464 //														 //
2465 //														 //
2466 //														 //
2467 ///////////////////////////////////////////////////////////
2468 
2469 //---------------------------------------------------------
2470