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