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 //                     grid_io.cpp                       //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'.                              //
22 //                                                       //
23 // This library is free software; you can redistribute   //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free       //
26 // Software Foundation, either version 2.1 of the        //
27 // License, or (at your option) any later version.       //
28 //                                                       //
29 // This library is distributed in the hope that it will  //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details.                             //
34 //                                                       //
35 // You should have received a copy of the GNU Lesser     //
36 // General Public License along with this program; if    //
37 // not, see <http://www.gnu.org/licenses/>.              //
38 //                                                       //
39 //-------------------------------------------------------//
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Hamburg                  //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include <stdint.h>
52 #include <string.h>
53 
54 #ifdef _SAGA_LINUX
55 #include "config.h"
56 #include <arpa/inet.h>
57 #include <netinet/in.h>
58 #else
59 #include <WinSock2.h>
60 #endif
61 
62 #include "grid.h"
63 #include "data_manager.h"
64 #include "tool_library.h"
65 
66 
67 ///////////////////////////////////////////////////////////
68 //														 //
69 //														 //
70 //														 //
71 ///////////////////////////////////////////////////////////
72 
73 //---------------------------------------------------------
On_Reload(void)74 bool CSG_Grid::On_Reload(void)
75 {
76 	return( Create(Get_File_Name(false)) );
77 }
78 
79 //---------------------------------------------------------
On_Delete(void)80 bool CSG_Grid::On_Delete(void)
81 {
82 	CSG_String	FileName	= Get_File_Name(true);
83 
84 	SG_File_Set_Extension(FileName, "sg-grd-z"); SG_File_Delete(FileName);
85 	SG_File_Set_Extension(FileName, "sg-grd"  ); SG_File_Delete(FileName);
86 	SG_File_Set_Extension(FileName, "sgrd"    ); SG_File_Delete(FileName);
87 	SG_File_Set_Extension(FileName, "sdat"    ); SG_File_Delete(FileName); SG_File_Delete(FileName + ".aux.xml");
88 	SG_File_Set_Extension(FileName, "mgrd"    ); SG_File_Delete(FileName);
89 	SG_File_Set_Extension(FileName, "dgm"     ); SG_File_Delete(FileName);
90 	SG_File_Set_Extension(FileName, "dat"     ); SG_File_Delete(FileName);
91 
92 	return( true );
93 }
94 
95 
96 ///////////////////////////////////////////////////////////
97 //														 //
98 //														 //
99 //														 //
100 ///////////////////////////////////////////////////////////
101 
102 //---------------------------------------------------------
103 static TSG_Grid_File_Format	gSG_Grid_File_Format_Default	= GRID_FILE_FORMAT_Binary_old;
104 
105 //---------------------------------------------------------
SG_Grid_Set_File_Format_Default(int Format)106 bool					SG_Grid_Set_File_Format_Default	(int Format)
107 {
108 	switch( Format )
109 	{
110 	case GRID_FILE_FORMAT_Binary_old:
111 	case GRID_FILE_FORMAT_Binary    :
112 	case GRID_FILE_FORMAT_Compressed:
113 	case GRID_FILE_FORMAT_ASCII     :
114 	case GRID_FILE_FORMAT_GeoTIFF   :
115 		gSG_Grid_File_Format_Default	= (TSG_Grid_File_Format)Format;
116 		return( true );
117 	}
118 
119 	return( false );
120 }
121 
122 //---------------------------------------------------------
SG_Grid_Get_File_Format_Default(void)123 TSG_Grid_File_Format	SG_Grid_Get_File_Format_Default	(void)
124 {
125 	return( gSG_Grid_File_Format_Default );
126 }
127 
128 //---------------------------------------------------------
SG_Grid_Get_File_Extension_Default(void)129 CSG_String				SG_Grid_Get_File_Extension_Default	(void)
130 {
131 	switch( gSG_Grid_File_Format_Default )
132 	{
133 	default:
134 	case GRID_FILE_FORMAT_Compressed:	return( "sg-grd-z" );
135 	case GRID_FILE_FORMAT_Binary    :	return( "sg-grd"   );
136 	case GRID_FILE_FORMAT_Binary_old:	return( "sgrd"     );
137 	case GRID_FILE_FORMAT_GeoTIFF   :	return( "tif"      );
138 	}
139 }
140 
141 
142 ///////////////////////////////////////////////////////////
143 //														 //
144 ///////////////////////////////////////////////////////////
145 
146 //---------------------------------------------------------
Save(const CSG_String & FileName,int Format)147 bool CSG_Grid::Save(const CSG_String &FileName, int Format)
148 {
149 	SG_UI_Msg_Add(CSG_String::Format("%s %s: %s...", _TL("Saving"), _TL("grid"), FileName.c_str()), true);
150 
151 	//-----------------------------------------------------
152 	if( Format == GRID_FILE_FORMAT_Undefined )
153 	{
154 		Format	= gSG_Grid_File_Format_Default;
155 
156 		if( SG_File_Cmp_Extension(FileName, "sg-grd-z") )	Format	= GRID_FILE_FORMAT_Compressed;
157 		if( SG_File_Cmp_Extension(FileName, "sg-grd"  ) )	Format	= GRID_FILE_FORMAT_Binary    ;
158 		if( SG_File_Cmp_Extension(FileName, "sgrd"    ) )	Format	= GRID_FILE_FORMAT_Binary_old;
159 		if( SG_File_Cmp_Extension(FileName, "tif"     ) )	Format	= GRID_FILE_FORMAT_GeoTIFF   ;
160 	}
161 
162 	//-----------------------------------------------------
163 	bool	bResult	= false;
164 
165 	switch( Format )
166 	{
167 	default:
168 		bResult = _Save_Native(FileName, (TSG_Grid_File_Format)Format);
169 		break;
170 
171 	case GRID_FILE_FORMAT_Compressed:
172 		bResult = _Save_Compressed(FileName);
173 		break;
174 
175 	case GRID_FILE_FORMAT_GeoTIFF:
176 		SG_RUN_TOOL(bResult, "io_gdal", 2,	// Export GeoTIFF
177 			    SG_TOOL_PARAMLIST_ADD("GRIDS", this)
178 			&&	SG_TOOL_PARAMETER_SET("FILE" , FileName)
179 		);
180 		break;
181 	}
182 
183 	SG_UI_Process_Set_Ready();
184 
185 	//-----------------------------------------------------
186 	if( bResult )
187 	{
188 		Set_Modified(false);
189 
190 		Set_File_Name(FileName, true);
191 
192 		SG_UI_Msg_Add(_TL("okay"), false, SG_UI_MSG_STYLE_SUCCESS);
193 
194 		return( true );
195 	}
196 
197 	SG_UI_Msg_Add(_TL("failed"), false, SG_UI_MSG_STYLE_FAILURE);
198 
199 	return( false );
200 }
201 
202 
203 ///////////////////////////////////////////////////////////
204 //														 //
205 //														 //
206 //														 //
207 ///////////////////////////////////////////////////////////
208 
209 //---------------------------------------------------------
_Load_External(const CSG_String & FileName,bool bCached,bool bLoadData)210 bool CSG_Grid::_Load_External(const CSG_String &FileName, bool bCached, bool bLoadData)
211 {
212 	bool	bResult	= false;
213 
214 	CSG_Data_Manager	Data;
215 
216 	CSG_Tool	*pTool	= NULL;
217 
218 	SG_UI_Msg_Lock(true);
219 
220 	//-----------------------------------------------------
221 	// Image Import
222 
223 	if( (	SG_File_Cmp_Extension(FileName, "bmp")
224 		||	SG_File_Cmp_Extension(FileName, "gif")
225 		||	SG_File_Cmp_Extension(FileName, "jpg")
226 		||	SG_File_Cmp_Extension(FileName, "png")
227 		||	SG_File_Cmp_Extension(FileName, "pcx") )
228 	&&  !bResult && (pTool = SG_Get_Tool_Library_Manager().Create_Tool("io_grid_image", 1)) != NULL )
229 	{
230 		pTool->Settings_Push(&Data);
231 
232 		bResult	=  pTool->Set_Parameter("FILE", FileName)
233 				&& pTool->Execute();
234 
235 		SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
236 	}
237 
238 	//-----------------------------------------------------
239 	// GDAL Import
240 
241 	if( !bResult && (pTool = SG_Get_Tool_Library_Manager().Create_Tool("io_gdal", 0)) != NULL )
242 	{
243 		pTool->Settings_Push(&Data);
244 
245 		bResult	=  pTool->Set_Parameter("FILES"   , FileName)
246 				&& pTool->Set_Parameter("MULTIPLE", 0       )	// output as single grid(s)
247 				&& pTool->Execute();
248 
249 		SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
250 	}
251 
252 	SG_UI_Msg_Lock(false);
253 
254 	//-----------------------------------------------------
255 	if( bResult && Data.Get_Grid_System(0) && Data.Get_Grid_System(0)->Get(0) && Data.Get_Grid_System(0)->Get(0)->is_Valid() )
256 	{
257 		CSG_Grid	*pGrid	= (CSG_Grid *)Data.Get_Grid_System(0)->Get(0);
258 
259 		if( pGrid->is_Cached() )
260 		{
261 			return( Create(*pGrid) );
262 		}
263 
264 		Set_File_Name(FileName, false);
265 
266 		Set_Name			(pGrid->Get_Name());
267 		Set_Description		(pGrid->Get_Description());
268 
269 		m_System			= pGrid->m_System;
270 		m_Type				= pGrid->m_Type;
271 		m_Values			= pGrid->m_Values;	pGrid->m_Values	= NULL;	// take ownership of data array
272 
273 		m_zOffset			= pGrid->m_zOffset;
274 		m_zScale			= pGrid->m_zScale;
275 		m_Unit				= pGrid->m_Unit;
276 
277 		m_nBytes_Value		= pGrid->m_nBytes_Value;
278 		m_nBytes_Line		= pGrid->m_nBytes_Line;
279 
280 		Get_MetaData  ()	= pGrid->Get_MetaData  ();
281 		Get_Projection()	= pGrid->Get_Projection();
282 
283 		Set_NoData_Value_Range(pGrid->Get_NoData_Value(), pGrid->Get_NoData_Value(true));
284 
285 		return( true );
286 	}
287 
288 	return( false );
289 }
290 
291 //---------------------------------------------------------
_Load_PGSQL(const CSG_String & FileName,bool bCached,bool bLoadData)292 bool CSG_Grid::_Load_PGSQL(const CSG_String &FileName, bool bCached, bool bLoadData)
293 {
294 	bool	bResult	= false;
295 
296 	if( FileName.BeforeFirst(':').Cmp("PGSQL") == 0 )	// database source
297 	{
298 		CSG_String	s(FileName);
299 
300 		s	= s.AfterFirst(':');	CSG_String	Host  (s.BeforeFirst(':'));
301 		s	= s.AfterFirst(':');	CSG_String	Port  (s.BeforeFirst(':'));
302 		s	= s.AfterFirst(':');	CSG_String	DBName(s.BeforeFirst(':'));
303 		s	= s.AfterFirst(':');	CSG_String	Table (s.BeforeFirst(':'));
304 		s	= s.AfterFirst(':');	CSG_String	rid   (s.BeforeFirst(':').AfterFirst('='));
305 
306 		CSG_Tool	*pTool	= SG_Get_Tool_Library_Manager().Create_Tool("db_pgsql", 0, true);	// CGet_Connections
307 
308 		if(	pTool != NULL )
309 		{
310 			SG_UI_ProgressAndMsg_Lock(true);
311 
312 			//---------------------------------------------
313 			CSG_Table	Connections;
314 			CSG_String	Connection	= DBName + " [" + Host + ":" + Port + "]";
315 
316 			pTool->Set_Manager(NULL);
317 			pTool->On_Before_Execution();
318 
319 			if( SG_TOOL_PARAMETER_SET("CONNECTIONS", &Connections) && pTool->Execute() )	// CGet_Connections
320 			{
321 				for(int i=0; !bResult && i<Connections.Get_Count(); i++)
322 				{
323 					if( !Connection.Cmp(Connections[i].asString(0)) )
324 					{
325 						bResult	= true;
326 					}
327 				}
328 			}
329 
330 			SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
331 
332 			//---------------------------------------------
333 			if( bResult && (bResult = (pTool = SG_Get_Tool_Library_Manager().Create_Tool("db_pgsql", 33, true)) != NULL) == true )	// CPGIS_Raster_Load_Band
334 			{
335 				pTool->Set_Manager(NULL);
336 				pTool->On_Before_Execution();
337 
338 				bResult	=  SG_TOOL_PARAMETER_SET("CONNECTION", Connection)
339 						&& SG_TOOL_PARAMETER_SET("TABLES"    , Table)
340 						&& SG_TOOL_PARAMETER_SET("RID"       , rid)
341 						&& SG_TOOL_PARAMETER_SET("GRID"      , this)
342 						&& pTool->Execute();
343 
344 				SG_Get_Tool_Library_Manager().Delete_Tool(pTool);
345 			}
346 
347 			SG_UI_ProgressAndMsg_Lock(false);
348 		}
349 	}
350 
351 	return( bResult );
352 }
353 
354 
355 ///////////////////////////////////////////////////////////
356 //														 //
357 //						Native							 //
358 //														 //
359 ///////////////////////////////////////////////////////////
360 
361 //---------------------------------------------------------
_Load_Native(const CSG_String & FileName,bool bCached,bool bLoadData)362 bool CSG_Grid::_Load_Native(const CSG_String &FileName, bool bCached, bool bLoadData)
363 {
364 	CSG_Grid_File_Info	Info;
365 
366 	if( !Info.Create(FileName) )
367 	{
368 		return( false );
369 	}
370 
371 	Set_File_Name(FileName, true);
372 
373 	Set_Name        (Info.m_Name);
374 	Set_Description (Info.m_Description);
375 	Set_Unit        (Info.m_Unit);
376 
377 	Set_NoData_Value_Range(Info.m_NoData[0], Info.m_NoData[1]);
378 
379 	m_System		= Info.m_System;
380 	m_Type			= Info.m_Type;
381 	m_zScale		= Info.m_zScale;
382 	m_zOffset		= Info.m_zOffset;
383 
384 	m_nBytes_Value	= SG_Data_Type_Get_Size(m_Type);
385 	m_nBytes_Line	= m_Type == SG_DATATYPE_Bit ? 1 + Get_NX() / 8 : Get_NX() * m_nBytes_Value;
386 
387 	Get_Projection().Load(SG_File_Make_Path("", FileName, "prj"), SG_PROJ_FMT_WKT);
388 
389 	if( !bLoadData )
390 	{
391 		return( _Memory_Create(bCached) );
392 	}
393 
394 	Load_MetaData(FileName);
395 
396 	//-----------------------------------------------------
397 	CSG_File	Stream;
398 
399 	if( !SG_Data_Type_is_Numeric(m_Type) )	// ASCII...
400 	{
401 		if(	Stream.Open(Info.m_Data_File                       , SG_FILE_R, false)
402 		||	Stream.Open(SG_File_Make_Path("", FileName,  "dat"), SG_FILE_R, false)
403 		||	Stream.Open(SG_File_Make_Path("", FileName, "sdat"), SG_FILE_R, false) )
404 		{
405 			Stream.Seek(Info.m_Offset);
406 
407 			return( _Load_ASCII(Stream, bCached, Info.m_bFlip) );
408 		}
409 	}
410 
411 	//-----------------------------------------------------
412 	else	// Binary...
413 	{
414 		if(	bCached || _Cache_Check() )
415 		{
416 			if( _Cache_Create(Info.m_Data_File                       , m_Type, Info.m_Offset, Info.m_bSwapBytes, Info.m_bFlip)
417 			||	_Cache_Create(SG_File_Make_Path("", FileName,  "dat"), m_Type, Info.m_Offset, Info.m_bSwapBytes, Info.m_bFlip)
418 			||	_Cache_Create(SG_File_Make_Path("", FileName, "sdat"), m_Type, Info.m_Offset, Info.m_bSwapBytes, Info.m_bFlip) )
419 			{
420 				return( true );
421 			}
422 		}
423 
424 		m_Cache_File	= Info.m_Data_File;
425 		m_Cache_Offset	= Info.m_Offset;
426 		m_Cache_bSwap	= Info.m_bSwapBytes;
427 		m_Cache_bFlip	= Info.m_bFlip;
428 
429 		if( _Memory_Create(bCached) )
430 		{
431 			if(	Stream.Open(Info.m_Data_File                       , SG_FILE_R, true)
432 			||	Stream.Open(SG_File_Make_Path("", FileName,  "dat"), SG_FILE_R, true)
433 			||	Stream.Open(SG_File_Make_Path("", FileName, "sdat"), SG_FILE_R, true) )
434 			{
435 				Stream.Seek(Info.m_Offset);
436 
437 				return( _Load_Binary(Stream, m_Type, Info.m_bFlip, Info.m_bSwapBytes) );
438 			}
439 		}
440 	}
441 
442 	return( false );
443 }
444 
445 //---------------------------------------------------------
_Save_Native(const CSG_String & _FileName,TSG_Grid_File_Format Format)446 bool CSG_Grid::_Save_Native(const CSG_String &_FileName, TSG_Grid_File_Format Format)
447 {
448 #ifdef WORDS_BIGENDIAN
449 	bool	bBigEndian	= true;
450 #else
451 	bool	bBigEndian	= false;
452 #endif
453 
454 	CSG_String	FileName(_FileName);
455 
456 	bool	bBinary;
457 
458 	if( Format == GRID_FILE_FORMAT_ASCII )
459 	{
460 		bBinary	= false;
461 	}
462 	else if( Format == GRID_FILE_FORMAT_Binary_old )
463 	{
464 		bBinary	= true;	SG_File_Set_Extension(FileName, "sgrd");
465 	}
466 	else
467 	{
468 		bBinary	= true;	SG_File_Set_Extension(FileName, "sg-grd");
469 	}
470 
471 	CSG_Grid_File_Info	Info(*this);
472 
473 	if(	Info.Save(FileName, bBinary) )
474 	{
475 		CSG_File	Stream(SG_File_Make_Path("", FileName, "sdat"), SG_FILE_W, true);
476 
477 		if( bBinary ? _Save_Binary(Stream, m_Type, false, bBigEndian) : _Save_ASCII (Stream) )
478 		{
479 			Save_MetaData(FileName);
480 
481 			Get_Projection().Save(SG_File_Make_Path("", FileName, "prj"), SG_PROJ_FMT_WKT);
482 
483 			Info.Save_AUX_XML(SG_File_Make_Path("", FileName, "sdat"));
484 
485 			return( true );
486 		}
487 	}
488 
489 	return( false );
490 }
491 
492 
493 ///////////////////////////////////////////////////////////
494 //														 //
495 //						Compressed						 //
496 //														 //
497 ///////////////////////////////////////////////////////////
498 
499 //---------------------------------------------------------
_Load_Compressed(const CSG_String & _FileName,bool bCached,bool bLoadData)500 bool CSG_Grid::_Load_Compressed(const CSG_String &_FileName, bool bCached, bool bLoadData)
501 {
502 	Set_File_Name(_FileName, true);
503 
504 	CSG_File_Zip	Stream(_FileName, SG_FILE_R);
505 
506 	if( !Stream.is_Reading() )
507 	{
508 		return( false );
509 	}
510 
511 	//-----------------------------------------------------
512 	CSG_String	FileName(SG_File_Get_Name(_FileName, false) + ".");
513 
514 	if( !Stream.Get_File(FileName + "sgrd"  )
515 	&&  !Stream.Get_File(FileName + "sg-grd") )
516 	{
517 		FileName.Clear();
518 
519 		for(size_t i=0; i<Stream.Get_File_Count(); i++)
520 		{
521 			if( SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sgrd"  )
522 			||  SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sg-grd") )
523 			{
524 				FileName	= SG_File_Get_Name(Stream.Get_File_Name(i), false) + ".";
525 				Stream.Get_File(Stream.Get_File_Name(i));
526 				break;
527 			}
528 		}
529 
530 		if( FileName.is_Empty() )
531 		{
532 			return( false );
533 		}
534 	}
535 
536 	//-----------------------------------------------------
537 	CSG_Grid_File_Info	Info;
538 
539 	if( !Info.Create(Stream) )
540 	{
541 		return( false );
542 	}
543 
544 	Set_Name        (Info.m_Name);
545 	Set_Description (Info.m_Description);
546 	Set_Unit        (Info.m_Unit);
547 
548 	Set_NoData_Value_Range(Info.m_NoData[0], Info.m_NoData[1]);
549 
550 	m_System		= Info.m_System;
551 	m_Type			= Info.m_Type;
552 	m_zScale		= Info.m_zScale;
553 	m_zOffset		= Info.m_zOffset;
554 
555 	m_nBytes_Value	= SG_Data_Type_Get_Size(m_Type);
556 	m_nBytes_Line	= m_Type == SG_DATATYPE_Bit ? 1 + Get_NX() / 8 : Get_NX() * m_nBytes_Value;
557 
558 	if( Stream.Get_File(FileName + "prj") )
559 	{
560 		Get_Projection().Load(Stream, SG_PROJ_FMT_WKT);
561 	}
562 
563 	if( !bLoadData )
564 	{
565 		return( _Memory_Create(bCached) );
566 	}
567 
568 	if( Stream.Get_File(FileName + "mgrd") )
569 	{
570 		Load_MetaData(Stream);
571 	}
572 
573 	//-----------------------------------------------------
574 	if( _Cache_Check() )
575 	{
576 		bCached	= true;
577 	}
578 
579 	return( Stream.Get_File(FileName + "sdat") && _Memory_Create(bCached)
580 		&& _Load_Binary(Stream, m_Type, Info.m_bFlip, Info.m_bSwapBytes)
581 	);
582 }
583 
584 //---------------------------------------------------------
_Save_Compressed(const CSG_String & _FileName)585 bool CSG_Grid::_Save_Compressed(const CSG_String &_FileName)
586 {
587 #ifdef WORDS_BIGENDIAN
588 	bool	bBigEndian	= true;
589 #else
590 	bool	bBigEndian	= false;
591 #endif
592 
593 	CSG_File_Zip	Stream(_FileName, SG_FILE_W);
594 
595 	if( Stream.is_Writing() )
596 	{
597 		CSG_String	FileName(SG_File_Get_Name(_FileName, false) + ".");
598 
599 		CSG_Grid_File_Info	Info(*this);
600 
601 		if( Stream.Add_File(FileName + "sgrd") && Info.Save(Stream, true)
602 		&&  Stream.Add_File(FileName + "sdat") && _Save_Binary(Stream, m_Type, false, bBigEndian) )
603 		{
604 			Stream.Add_File(FileName + "mgrd"        ); Save_MetaData(Stream);
605 			Stream.Add_File(FileName + "prj"         ); Get_Projection().Save(Stream, SG_PROJ_FMT_WKT);
606 			Stream.Add_File(FileName + "sdat.aux.xml"); Info.Save_AUX_XML(Stream);
607 
608 			return( true );
609 		}
610 	}
611 
612 	return( false );
613 }
614 
615 
616 ///////////////////////////////////////////////////////////
617 //														 //
618 //						Binary							 //
619 //														 //
620 ///////////////////////////////////////////////////////////
621 
622 //---------------------------------------------------------
_Swap_Bytes(char * Bytes,int nBytes) const623 void CSG_Grid::_Swap_Bytes(char *Bytes, int nBytes) const
624 {
625 	if( nBytes == 2 )
626 	{
627 		uint16_t val, valSwapped;
628 		memcpy(&val, Bytes, nBytes);
629 		valSwapped = ntohs(val);
630 		memcpy(Bytes, &valSwapped, nBytes);
631 	}
632 	else if( nBytes == 4 )
633 	{
634 		uint32_t val, valSwapped;
635 		memcpy(&val, Bytes, nBytes);
636 		valSwapped = ntohl(val);
637 		memcpy(Bytes, &valSwapped, nBytes);
638 	}
639 }
640 
641 //---------------------------------------------------------
_Load_Binary(CSG_File & Stream,TSG_Data_Type File_Type,bool bFlip,bool bSwapBytes)642 bool CSG_Grid::_Load_Binary(CSG_File &Stream, TSG_Data_Type File_Type, bool bFlip, bool bSwapBytes)
643 {
644 	if( !Stream.is_Open() || !is_Valid() )
645 	{
646 		return( false );
647 	}
648 
649 	Set_File_Type(GRID_FILE_FORMAT_Binary);
650 
651 	//-----------------------------------------------------
652 	if( File_Type == SG_DATATYPE_Bit )
653 	{
654 		int	nLineBytes	= Get_NX() / 8 + 1;
655 
656 		if( m_Type == File_Type && !is_Cached() )
657 		{
658 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
659 			{
660 				Stream.Read(m_Values[bFlip ? Get_NY() - y - 1 : y], sizeof(char), nLineBytes);
661 			}
662 		}
663 		else
664 		{
665 			CSG_Array	Line(1, nLineBytes);
666 
667 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
668 			{
669 				Stream.Read(Line.Get_Array(), nLineBytes);
670 
671 				char	*pValue	= (char *)Line.Get_Array();
672 
673 				for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); pValue++)
674 				{
675 					for(int i=0; i<8 && x<Get_NX(); i++, x++)
676 					{
677 						Set_Value(x, yy, (*pValue & m_Bitmask[i]) == 0 ? 0.0 : 1.0);
678 					}
679 				}
680 			}
681 		}
682 	}
683 
684 	//-----------------------------------------------------
685 	else
686 	{
687 		int	nValueBytes	= (int)SG_Data_Type_Get_Size(File_Type);
688 		int	nLineBytes	= Get_NX() * nValueBytes;
689 
690 		if( m_Type == File_Type && !is_Cached() && !bSwapBytes )
691 		{
692 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
693 			{
694 				Stream.Read(m_Values[bFlip ? Get_NY() - y - 1 : y], nLineBytes);
695 			}
696 		}
697 		else
698 		{
699 			CSG_Array	Line(1, nLineBytes);
700 
701 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
702 			{
703 				Stream.Read(Line.Get_Array(), nLineBytes);
704 
705 				char	*pValue	= (char *)Line.Get_Array();
706 
707 				for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); x++, pValue+=nValueBytes)
708 				{
709 					if( bSwapBytes )
710 					{
711 						_Swap_Bytes(pValue, nValueBytes);
712 					}
713 
714 					switch( File_Type )
715 					{
716 					case SG_DATATYPE_Byte  : Set_Value(x, yy, *(BYTE   *)pValue, false); break;
717 					case SG_DATATYPE_Char  : Set_Value(x, yy, *(char   *)pValue, false); break;
718 					case SG_DATATYPE_Word  : Set_Value(x, yy, *(WORD   *)pValue, false); break;
719 					case SG_DATATYPE_Short : Set_Value(x, yy, *(short  *)pValue, false); break;
720 					case SG_DATATYPE_DWord : Set_Value(x, yy, *(DWORD  *)pValue, false); break;
721 					case SG_DATATYPE_Int   : Set_Value(x, yy, *(int    *)pValue, false); break;
722 					case SG_DATATYPE_Float : Set_Value(x, yy, *(float  *)pValue, false); break;
723 					case SG_DATATYPE_Double: Set_Value(x, yy, *(double *)pValue, false); break;
724 					default:	break;
725 					}
726 				}
727 			}
728 		}
729 	}
730 
731 	//-----------------------------------------------------
732 	return( true );
733 }
734 
735 //---------------------------------------------------------
_Save_Binary(CSG_File & Stream,TSG_Data_Type File_Type,bool bFlip,bool bSwapBytes)736 bool CSG_Grid::_Save_Binary(CSG_File &Stream, TSG_Data_Type File_Type, bool bFlip, bool bSwapBytes)
737 {
738 	//-----------------------------------------------------
739 	if( !Stream.is_Writing() || !is_Valid() )
740 	{
741 		return( false );
742 	}
743 
744 	Set_File_Type(GRID_FILE_FORMAT_Binary);
745 
746 	//-----------------------------------------------------
747 	if( File_Type == SG_DATATYPE_Bit )
748 	{
749 		int	nLineBytes	= Get_NX() / 8 + 1;
750 
751 		if( m_Type == File_Type && !is_Cached() )
752 		{
753 			for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
754 			{
755 				Stream.Write((char *)m_Values[bFlip ? Get_NY() - y - 1 : y], sizeof(char), nLineBytes);
756 			}
757 		}
758 		else
759 		{
760 			CSG_Array	Line(1, nLineBytes);
761 
762 			for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
763 			{
764 				char	*pValue	= (char *)Line.Get_Array();
765 
766 				for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); pValue++)
767 				{
768 					for(int i=0; i<8 && x<Get_NX(); i++, x++)
769 					{
770 						*pValue	= asChar(x, yy) != 0.0 ? *pValue | m_Bitmask[i] : *pValue & (~m_Bitmask[i]);
771 					}
772 				}
773 
774 				Stream.Write(Line.Get_Array(), nLineBytes);
775 			}
776 		}
777 	}
778 
779 	//-----------------------------------------------------
780 	else
781 	{
782 		int	nValueBytes	= (int)SG_Data_Type_Get_Size(File_Type);
783 		int	nLineBytes	= Get_NX() * nValueBytes;
784 
785 		if( m_Type == File_Type && !is_Cached() && !bSwapBytes )
786 		{
787 			for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
788 			{
789 				Stream.Write((char *)m_Values[bFlip ? Get_NY() - y - 1 : y], nLineBytes);
790 			}
791 		}
792 		else
793 		{
794 			CSG_Array	Line(1, nLineBytes);
795 
796 			for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
797 			{
798 				char	*pValue	= (char *)Line.Get_Array();
799 
800 				for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); x++, pValue+=nValueBytes)
801 				{
802 					switch( File_Type )
803 					{
804 					case SG_DATATYPE_Byte  : *(BYTE   *)pValue = asByte  (x, yy, false); break;
805 					case SG_DATATYPE_Char  : *(char   *)pValue = asChar  (x, yy, false); break;
806 					case SG_DATATYPE_Word  : *(WORD   *)pValue = asShort (x, yy, false); break;
807 					case SG_DATATYPE_Short : *(short  *)pValue = asShort (x, yy, false); break;
808 					case SG_DATATYPE_DWord : *(DWORD  *)pValue = asInt   (x, yy, false); break;
809 					case SG_DATATYPE_Int   : *(int    *)pValue = asInt   (x, yy, false); break;
810 					case SG_DATATYPE_Float : *(float  *)pValue = asFloat (x, yy, false); break;
811 					case SG_DATATYPE_Double: *(double *)pValue = asDouble(x, yy, false); break;
812 					default:	break;
813 					}
814 
815 					if( bSwapBytes )
816 					{
817 						_Swap_Bytes(pValue, nValueBytes);
818 					}
819 				}
820 
821 				Stream.Write(Line.Get_Array(), nLineBytes);
822 			}
823 		}
824 	}
825 
826 	//-----------------------------------------------------
827 	return( true );
828 }
829 
830 
831 ///////////////////////////////////////////////////////////
832 //														 //
833 //							ASCII						 //
834 //														 //
835 ///////////////////////////////////////////////////////////
836 
837 //---------------------------------------------------------
_Load_ASCII(CSG_File & Stream,bool bCached,bool bFlip)838 bool CSG_Grid::_Load_ASCII(CSG_File &Stream, bool bCached, bool bFlip)
839 {
840 	if( !Stream.is_Reading() || !_Memory_Create(bCached) )
841 	{
842 		return( false );
843 	}
844 
845 	Set_File_Type(GRID_FILE_FORMAT_ASCII);
846 
847 	for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
848 	{
849 		for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); x++)
850 		{
851 			Set_Value(x, yy, Stream.Scan_Double());
852 		}
853 	}
854 
855 	return( true );
856 }
857 
858 //---------------------------------------------------------
_Save_ASCII(CSG_File & Stream,bool bFlip)859 bool CSG_Grid::_Save_ASCII(CSG_File &Stream, bool bFlip)
860 {
861 	if( !Stream.is_Writing() || !is_Valid() )
862 	{
863 		return( false );
864 	}
865 
866 	Set_File_Type(GRID_FILE_FORMAT_ASCII);
867 
868 	for(int y=0; y<Get_NY() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
869 	{
870 		for(int x=0, yy=bFlip ? Get_NY()-y-1 : y; x<Get_NX(); x++)
871 		{
872 			Stream.Printf("%lf ", asDouble(x, yy));
873 		}
874 
875 		Stream.Printf("\n");
876 	}
877 
878 	return( true );
879 }
880 
881 
882 ///////////////////////////////////////////////////////////
883 //														 //
884 ///////////////////////////////////////////////////////////
885 
886 //---------------------------------------------------------
_Load_Surfer(const CSG_String & FileName,bool bCached,bool bLoadData)887 bool CSG_Grid::_Load_Surfer(const CSG_String &FileName, bool bCached, bool bLoadData)
888 {
889 	const float	NoData	= 1.70141e38f;
890 
891 	if( !SG_File_Cmp_Extension(FileName, "grd") )
892 	{
893 		return( false );
894 	}
895 
896 	Set_File_Name(FileName, true);
897 
898 	//-----------------------------------------------------
899 	CSG_File	Stream;
900 
901 	if( !Stream.Open(FileName, SG_FILE_R, true) )
902 	{
903 		return( false );
904 	}
905 
906 	char	Identifier[4];
907 
908 	Stream.Read(Identifier, sizeof(char), 4);
909 
910 	//-----------------------------------------------------
911 	if( !strncmp(Identifier, "DSBB", 4) )	// Binary...
912 	{
913 		short		nx, ny;
914 		double		d;
915 		TSG_Rect	r;
916 
917 		Stream.Read(&nx    , sizeof(short ));
918 		Stream.Read(&ny    , sizeof(short ));
919 		Stream.Read(&r.xMin, sizeof(double));
920 		Stream.Read(&r.xMax, sizeof(double));
921 		Stream.Read(&r.yMin, sizeof(double));
922 		Stream.Read(&r.yMax, sizeof(double));
923 		Stream.Read(&d     , sizeof(double));	// zMin
924 		Stream.Read(&d     , sizeof(double));	// zMax
925 
926 		d	= (r.xMax - r.xMin) / (nx - 1.0);
927 	//	d	= (r.yMax - r.yMin) / (ny - 1.0);	// we could proof for equal cellsize in direction of y...
928 
929 		//-------------------------------------------------
930 		if( !Create(SG_DATATYPE_Float, nx, ny, d, r.xMin, r.yMin, bCached) || Stream.is_EOF() )
931 		{
932 			return( false );
933 		}
934 
935 		//-------------------------------------------------
936 		if( bLoadData )
937 		{
938 			CSG_Array	Line(sizeof(float), Get_NX());	float *Values = (float *)Line.Get_Array();
939 
940 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
941 			{
942 				Stream.Read(Values, sizeof(float), Get_NX());
943 
944 				for(int x=0; x<Get_NX(); x++)
945 				{
946 					if( Values[x] == NoData )
947 					{
948 						Set_NoData(x, y);
949 					}
950 					else
951 					{
952 						Set_Value(x, y, Values[x]);
953 					}
954 				}
955 			}
956 		}
957 
958 		Get_MetaData().Add_Child("SURFER_GRID", "Surfer Grid (Binary)");
959 	}
960 
961 	//-----------------------------------------------------
962 	else if( !strncmp(Identifier, "DSAA", 4) )	// ASCII...
963 	{
964 		int		nx		= Stream.Scan_Int   ();
965 		int		ny		= Stream.Scan_Int   ();
966 		double	xMin	= Stream.Scan_Double();
967 		double	xMax	= Stream.Scan_Double();
968 		double	yMin	= Stream.Scan_Double(); Stream.Scan_Double();
969 	//	double	yMax	= Stream.Scan_Double();
970 		double	dx		= Stream.Scan_Double(); Stream.Scan_Double();
971 	//	double	dy		= Stream.Scan_Double();
972 
973 		dx	= (xMax - xMin) / (nx - 1.0);
974 	//	dy	= (yMax - yMin) / (ny - 1.0);	// we could proof for equal cellsize in direction of y...
975 
976 		//-------------------------------------------------
977 		if( !Create(SG_DATATYPE_Float, nx, ny, dx, xMin, yMin, bCached) || Stream.is_EOF() )
978 		{
979 			return( false );
980 		}
981 
982 		//-------------------------------------------------
983 		if( bLoadData )
984 		{
985 			for(int y=0; y<Get_NY() && !Stream.is_EOF() && SG_UI_Process_Set_Progress(y, Get_NY()); y++)
986 			{
987 				for(int x=0; x<Get_NX(); x++)
988 				{
989 					double	Value;
990 
991 					if( Stream.Scan(Value) && Value != NoData )
992 					{
993 						Set_Value(x, y, Value);
994 					}
995 					else
996 					{
997 						Set_NoData(x, y);
998 					}
999 				}
1000 			}
1001 		}
1002 
1003 		Get_MetaData().Add_Child("SURFER_GRID", "Surfer Grid (ASCII)");
1004 	}
1005 
1006 	//-------------------------------------------------
1007 	SG_UI_Process_Set_Ready();
1008 
1009 	Set_File_Name(FileName);
1010 	Load_MetaData(FileName);
1011 
1012 	return( true );
1013 }
1014 
1015 
1016 ///////////////////////////////////////////////////////////
1017 //														 //
1018 //														 //
1019 //														 //
1020 ///////////////////////////////////////////////////////////
1021 
1022 //---------------------------------------------------------
CSG_Grid_File_Info(void)1023 CSG_Grid_File_Info::CSG_Grid_File_Info(void)
1024 {
1025 	_On_Construction();
1026 }
1027 
_On_Construction(void)1028 void CSG_Grid_File_Info::_On_Construction(void)
1029 {
1030 	m_Name			.Clear();
1031 	m_Description	.Clear();
1032 	m_Unit			.Clear();
1033 	m_System		.Assign(0.0, 0.0, 0.0, 0, 0);
1034 	m_Type			= SG_DATATYPE_Float;	// defaults to float
1035 	m_zScale		= 1.0;
1036 	m_zOffset		= 0;
1037 	m_NoData[0]		= -99999.0;
1038 	m_NoData[1]		= -99999.0;
1039 	m_Data_File		.Clear();
1040 	m_bFlip			= false;
1041 	m_bSwapBytes	= false;
1042 	m_Offset		= 0;
1043 	m_Projection	.Destroy();
1044 }
1045 
1046 //---------------------------------------------------------
CSG_Grid_File_Info(const CSG_Grid_File_Info & Info)1047 CSG_Grid_File_Info::CSG_Grid_File_Info(const CSG_Grid_File_Info &Info)
1048 {
1049 	Create(Info);
1050 }
1051 
Create(const CSG_Grid_File_Info & Info)1052 bool CSG_Grid_File_Info::Create(const CSG_Grid_File_Info &Info)
1053 {
1054 	m_Name			= Info.m_Name;
1055 	m_Description	= Info.m_Description;
1056 	m_Unit			= Info.m_Unit;
1057 	m_System		= Info.m_System;
1058 	m_Type			= Info.m_Type;
1059 	m_zScale		= Info.m_zScale;
1060 	m_zOffset		= Info.m_zOffset;
1061 	m_NoData[0]		= Info.m_NoData[0];
1062 	m_NoData[1]		= Info.m_NoData[1];
1063 	m_Data_File		= Info.m_Data_File;
1064 	m_bFlip			= Info.m_bFlip;
1065 	m_bSwapBytes	= Info.m_bSwapBytes;
1066 	m_Offset		= Info.m_Offset;
1067 	m_Projection	= Info.m_Projection;
1068 
1069 	return( true );
1070 }
1071 
1072 //---------------------------------------------------------
CSG_Grid_File_Info(const CSG_Grid & Grid)1073 CSG_Grid_File_Info::CSG_Grid_File_Info(const CSG_Grid &Grid)
1074 {
1075 	Create(Grid);
1076 }
1077 
Create(const CSG_Grid & Grid)1078 bool CSG_Grid_File_Info::Create(const CSG_Grid &Grid)
1079 {
1080 	m_Name			= Grid.Get_Name();
1081 	m_Description	= Grid.Get_Description();
1082 	m_Unit			= Grid.Get_Unit();
1083 	m_System		= Grid.Get_System();
1084 	m_Type			= Grid.Get_Type();
1085 	m_zScale		= Grid.Get_Scaling();
1086 	m_zOffset		= Grid.Get_Offset();
1087 	m_NoData[0]		= Grid.Get_NoData_Value();
1088 	m_NoData[1]		= Grid.Get_NoData_Value(true);
1089 	m_Data_File		.Clear();
1090 	m_bFlip			= false;
1091 	m_bSwapBytes	= false;
1092 	m_Offset		= 0;
1093 	m_Projection	= Grid.Get_Projection();
1094 
1095 	return( true );
1096 }
1097 
1098 //---------------------------------------------------------
CSG_Grid_File_Info(const CSG_String & FileName)1099 CSG_Grid_File_Info::CSG_Grid_File_Info(const CSG_String &FileName)
1100 {
1101 	Create(FileName);
1102 }
1103 
Create(const CSG_String & FileName)1104 bool CSG_Grid_File_Info::Create(const CSG_String &FileName)
1105 {
1106 	if( !SG_File_Cmp_Extension(FileName, "sg-grd-z") )
1107 	{
1108 		if( SG_File_Cmp_Extension(FileName, "sgrd")
1109 		||  SG_File_Cmp_Extension(FileName, "sg-grd") )
1110 		{
1111 			CSG_File	Stream(FileName, SG_FILE_R, false);
1112 
1113 			return( Create(Stream) );
1114 		}
1115 
1116 		return( false );
1117 	}
1118 
1119 	//-----------------------------------------------------
1120 	CSG_File_Zip	Stream(FileName, SG_FILE_R);
1121 
1122 	if( Stream.is_Reading() )
1123 	{
1124 		CSG_String	File(SG_File_Get_Name(FileName, false) + ".");
1125 
1126 		if( !Stream.Get_File(File + "sgrd"  )
1127 		&&  !Stream.Get_File(File + "sg-grd") )
1128 		{
1129 			for(size_t i=0; i<Stream.Get_File_Count(); i++)
1130 			{
1131 				if( SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sgrd"  )
1132 				||  SG_File_Cmp_Extension(Stream.Get_File_Name(i), "sg-grd") )
1133 				{
1134 					Stream.Get_File(Stream.Get_File_Name(i));
1135 					break;
1136 				}
1137 			}
1138 		}
1139 
1140 		return( Create(Stream) );
1141 	}
1142 
1143 	//-----------------------------------------------------
1144 	return( false );
1145 }
1146 
1147 //---------------------------------------------------------
CSG_Grid_File_Info(CSG_File & Stream)1148 CSG_Grid_File_Info::CSG_Grid_File_Info(CSG_File &Stream)
1149 {
1150 	Create(Stream);
1151 }
1152 
Create(CSG_File & Stream)1153 bool CSG_Grid_File_Info::Create(CSG_File &Stream)
1154 {
1155 	_On_Construction();
1156 
1157 	//-----------------------------------------------------
1158 	if( !Stream.is_Reading() )
1159 	{
1160 		return( false );
1161 	}
1162 
1163 	//-----------------------------------------------------
1164 	sLong	NX = 0, NY = 0;
1165 	double	Cellsize = 0.0, xMin = 0.0, yMin = 0.0;
1166 
1167 	do
1168 	{
1169 		CSG_String	Value;
1170 
1171 		switch( _Get_Key(Stream, Value) )
1172 		{
1173 		case GRID_FILE_KEY_NAME           :	m_Name        = Value;	break;
1174 		case GRID_FILE_KEY_DESCRIPTION    :	m_Description = Value;	break;
1175 		case GRID_FILE_KEY_UNITNAME       :	m_Unit        = Value;	break;
1176 
1177 		case GRID_FILE_KEY_CELLCOUNT_X    :	NX            = Value.asInt   ();	break;
1178 		case GRID_FILE_KEY_CELLCOUNT_Y    :	NY            = Value.asInt   ();	break;
1179 		case GRID_FILE_KEY_POSITION_XMIN  :	xMin          = Value.asDouble();	break;
1180 		case GRID_FILE_KEY_POSITION_YMIN  :	yMin          = Value.asDouble();	break;
1181 		case GRID_FILE_KEY_CELLSIZE       :	Cellsize      = Value.asDouble();	break;
1182 
1183 		case GRID_FILE_KEY_Z_FACTOR       :	m_zScale      = Value.asDouble();	break;
1184 		case GRID_FILE_KEY_Z_OFFSET       :	m_zOffset     = Value.asDouble();	break;
1185 		case GRID_FILE_KEY_NODATA_VALUE   :	m_NoData[0]   = Value.asDouble();
1186 			Value = Value.AfterFirst(';');  m_NoData[1]   = Value.is_Empty() ? m_NoData[0] : Value.asDouble();	break;
1187 
1188 		case GRID_FILE_KEY_DATAFILE_OFFSET:	m_Offset      = Value.asInt   ();	break;
1189 		case GRID_FILE_KEY_BYTEORDER_BIG  :	m_bSwapBytes  = Value.Find(GRID_FILE_KEY_TRUE) >= 0;	break;
1190 		case GRID_FILE_KEY_TOPTOBOTTOM    :	m_bFlip       = Value.Find(GRID_FILE_KEY_TRUE) >= 0;	break;
1191 
1192 		case GRID_FILE_KEY_DATAFILE_NAME:
1193 			if( SG_File_Get_Path(Value).Length() > 0 )
1194 			{
1195 				m_Data_File	= Value;
1196 			}
1197 			else
1198 			{
1199 				m_Data_File	= SG_File_Make_Path(SG_File_Get_Path(Stream.Get_File_Name()), Value);
1200 			}
1201 			break;
1202 
1203 		case GRID_FILE_KEY_DATAFORMAT:
1204 			{
1205 				for(int i=0; i<SG_DATATYPE_Undefined; i++)
1206 				{
1207 					if( Value.Find(gSG_Data_Type_Identifier[i]) >= 0 )
1208 					{
1209 						m_Type	= (TSG_Data_Type)i;
1210 
1211 						break;
1212 					}
1213 				}
1214 			}
1215 			break;
1216 		}
1217 	}
1218 	while( !Stream.is_EOF() );
1219 
1220 	//-----------------------------------------------------
1221 	return( m_System.Assign(Cellsize, xMin, yMin, (int)NX, (int)NY) );
1222 }
1223 
1224 //---------------------------------------------------------
_Get_Key(CSG_File & Stream,CSG_String & Value)1225 int CSG_Grid_File_Info::_Get_Key(CSG_File &Stream, CSG_String &Value)
1226 {
1227 	int			i;
1228 	CSG_String	sLine;
1229 
1230 	if( Stream.Read_Line(sLine) && (i = sLine.Find('=')) > 0 )
1231 	{
1232 		Value	= sLine.AfterFirst('=');
1233 		Value.Trim();
1234 
1235 		sLine.Remove(i);
1236 
1237 		for(i=0; i<GRID_FILE_KEY_Count; i++)
1238 		{
1239 			CSG_String	s(gSG_Grid_File_Key_Names[i]);
1240 
1241 			if( s.Find(sLine.Left(s.Length())) >= 0 )
1242 			{
1243 				return( i );
1244 			}
1245 		}
1246 	}
1247 
1248 	return( -1 );
1249 }
1250 
1251 
1252 ///////////////////////////////////////////////////////////
1253 //														 //
1254 ///////////////////////////////////////////////////////////
1255 
1256 //---------------------------------------------------------
Save(const CSG_String & FileName,bool bBinary)1257 bool CSG_Grid_File_Info::Save(const CSG_String &FileName, bool bBinary)
1258 {
1259 	return( Save(CSG_File(FileName, SG_FILE_W, false), bBinary) );
1260 }
1261 
1262 //---------------------------------------------------------
Save(const CSG_File & Stream,bool bBinary)1263 bool CSG_Grid_File_Info::Save(const CSG_File &Stream, bool bBinary)
1264 {
1265 	if(	!Stream.is_Writing() )
1266 	{
1267 		return( false );
1268 	}
1269 
1270 #define GRID_FILE_PRINT(Key, Val)	{ CSG_String s(gSG_Grid_File_Key_Names[Key]); s += "\t= " + Val + "\n"; Stream.Write(s); }
1271 
1272 	GRID_FILE_PRINT(GRID_FILE_KEY_NAME           , CSG_String::Format("%s"   , m_Name       .c_str()   ));
1273 	GRID_FILE_PRINT(GRID_FILE_KEY_DESCRIPTION    , CSG_String::Format("%s"   , m_Description.c_str()   ));
1274 	GRID_FILE_PRINT(GRID_FILE_KEY_UNITNAME       , CSG_String::Format("%s"   , m_Unit       .c_str()   ));
1275 	GRID_FILE_PRINT(GRID_FILE_KEY_DATAFORMAT     , CSG_String::Format("%s"   , CSG_String(bBinary ? gSG_Data_Type_Identifier[m_Type] : "ASCII").c_str()));
1276 	GRID_FILE_PRINT(GRID_FILE_KEY_DATAFILE_OFFSET, CSG_String::Format("%d"   , 0                       ));
1277 #ifdef WORDS_BIGENDIAN
1278 	GRID_FILE_PRINT(GRID_FILE_KEY_BYTEORDER_BIG  , CSG_String::Format("%s"   , GRID_FILE_KEY_TRUE      ));
1279 #else
1280 	GRID_FILE_PRINT(GRID_FILE_KEY_BYTEORDER_BIG  , CSG_String::Format("%s"   , GRID_FILE_KEY_FALSE     ));
1281 #endif
1282 	GRID_FILE_PRINT(GRID_FILE_KEY_TOPTOBOTTOM    , CSG_String::Format("%s"   , GRID_FILE_KEY_FALSE     ));
1283 	GRID_FILE_PRINT(GRID_FILE_KEY_POSITION_XMIN  , CSG_String::Format("%.*f" , CSG_Grid_System::Get_Precision(), m_System.Get_XMin()));
1284 	GRID_FILE_PRINT(GRID_FILE_KEY_POSITION_YMIN  , CSG_String::Format("%.*f" , CSG_Grid_System::Get_Precision(), m_System.Get_YMin()));
1285 	GRID_FILE_PRINT(GRID_FILE_KEY_CELLCOUNT_X    , CSG_String::Format("%d"   , m_System.Get_NX()       ));
1286 	GRID_FILE_PRINT(GRID_FILE_KEY_CELLCOUNT_Y    , CSG_String::Format("%d"   , m_System.Get_NY()       ));
1287 	GRID_FILE_PRINT(GRID_FILE_KEY_CELLSIZE       , CSG_String::Format("%.*f" , CSG_Grid_System::Get_Precision(), m_System.Get_Cellsize()));
1288 	GRID_FILE_PRINT(GRID_FILE_KEY_Z_FACTOR       , CSG_String::Format("%f"   , m_zScale                ));
1289 	GRID_FILE_PRINT(GRID_FILE_KEY_Z_OFFSET       , CSG_String::Format("%f"   , m_zOffset               ));
1290 	GRID_FILE_PRINT(GRID_FILE_KEY_NODATA_VALUE   , CSG_String::Format("%f;%f", m_NoData[0], m_NoData[1]));
1291 
1292 	return( true );
1293 }
1294 
1295 //---------------------------------------------------------
Save(const CSG_String & FileName,const CSG_Grid & Grid,bool bBinary)1296 bool CSG_Grid_File_Info::Save(const CSG_String &FileName, const CSG_Grid &Grid, bool bBinary)
1297 {
1298 	CSG_Grid_File_Info	Info(Grid);
1299 
1300 	return( Info.Save(FileName, bBinary) );
1301 }
1302 
1303 //---------------------------------------------------------
Save(const CSG_File & Stream,const CSG_Grid & Grid,bool bBinary)1304 bool CSG_Grid_File_Info::Save(const CSG_File &Stream, const CSG_Grid &Grid, bool bBinary)
1305 {
1306 	CSG_Grid_File_Info	Info(Grid);
1307 
1308 	return( Info.Save(Stream, bBinary) );
1309 }
1310 
1311 
1312 ///////////////////////////////////////////////////////////
1313 //														 //
1314 ///////////////////////////////////////////////////////////
1315 
1316 //---------------------------------------------------------
Save_AUX_XML(const CSG_String & FileName)1317 bool CSG_Grid_File_Info::Save_AUX_XML(const CSG_String &FileName)
1318 {
1319 	CSG_File	Stream;
1320 
1321 	return( m_Projection.is_Okay() && Stream.Open(FileName + ".aux.xml", SG_FILE_W, false) && Save_AUX_XML(Stream) );
1322 }
1323 
1324 //---------------------------------------------------------
Save_AUX_XML(CSG_File & Stream)1325 bool CSG_Grid_File_Info::Save_AUX_XML(CSG_File &Stream)
1326 {
1327 	if( m_Projection.is_Okay() && Stream.is_Writing() )	// store srs information that is recognized by ArcGIS
1328 	{
1329 		Stream.Write("<PAMDataset>\n<SRS>");
1330 		Stream.Write(m_Projection.Get_WKT());
1331 		Stream.Write("</SRS>\n</PAMDataset>\n");
1332 
1333 		return( true );
1334 	}
1335 
1336 	return( false );
1337 }
1338 
1339 
1340 ///////////////////////////////////////////////////////////
1341 //														 //
1342 //														 //
1343 //														 //
1344 ///////////////////////////////////////////////////////////
1345 
1346 //---------------------------------------------------------
1347