📄 grid_memory.cpp
字号:
///////////////////////////////////////////////////////////
// //
// SAGA //
// //
// System for Automated Geoscientific Analyses //
// //
// Application Programming Interface //
// //
// Library: SAGA_API //
// //
//-------------------------------------------------------//
// //
// grid_memory.cpp //
// //
// Copyright (C) 2005 by Olaf Conrad //
// //
//-------------------------------------------------------//
// //
// This file is part of 'SAGA - System for Automated //
// Geoscientific Analyses'. //
// //
// This library is free software; you can redistribute //
// it and/or modify it under the terms of the GNU Lesser //
// General Public License as published by the Free //
// Software Foundation, version 2.1 of the License. //
// //
// This library is distributed in the hope that it will //
// be useful, but WITHOUT ANY WARRANTY; without even the //
// implied warranty of MERCHANTABILITY or FITNESS FOR A //
// PARTICULAR PURPOSE. See the GNU Lesser General Public //
// License for more details. //
// //
// You should have received a copy of the GNU Lesser //
// General Public License along with this program; if //
// not, write to the Free Software Foundation, Inc., //
// 59 Temple Place - Suite 330, Boston, MA 02111-1307, //
// USA. //
// //
//-------------------------------------------------------//
// //
// contact: Olaf Conrad //
// Institute of Geography //
// University of Goettingen //
// Goldschmidtstr. 5 //
// 37077 Goettingen //
// Germany //
// //
// e-mail: oconrad@saga-gis.org //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
#include <memory.h>
#include "grid.h"
#include "parameters.h"
///////////////////////////////////////////////////////////
// //
// Caching Options //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
static CSG_String gSG_Grid_Cache_Directory;
const SG_Char * SG_Grid_Cache_Get_Directory(void)
{
return( gSG_Grid_Cache_Directory );
}
void SG_Grid_Cache_Set_Directory(const SG_Char *Directory)
{
if( SG_Dir_Exists(Directory) )
{
gSG_Grid_Cache_Directory.Printf(Directory);
}
}
//---------------------------------------------------------
static bool gSG_Grid_Cache_bAutomatic = false;
void SG_Grid_Cache_Set_Automatic(bool bOn)
{
gSG_Grid_Cache_bAutomatic = bOn;
}
bool SG_Grid_Cache_Get_Automatic(void)
{
return( gSG_Grid_Cache_bAutomatic );
}
//---------------------------------------------------------
static int gSG_Grid_Cache_Confirm = 1;
void SG_Grid_Cache_Set_Confirm(int Confirm)
{
gSG_Grid_Cache_Confirm = Confirm;
}
int SG_Grid_Cache_Get_Confirm(void)
{
return( gSG_Grid_Cache_Confirm );
}
//---------------------------------------------------------
static int gSG_Grid_Cache_Threshold = 40 * N_MEGABYTE_BYTES;
void SG_Grid_Cache_Set_Threshold(int nBytes)
{
if( nBytes >= 0 )
{
gSG_Grid_Cache_Threshold = nBytes;
}
}
void SG_Grid_Cache_Set_Threshold_MB(double nMegabytes)
{
SG_Grid_Cache_Set_Threshold((int)(nMegabytes * N_MEGABYTE_BYTES));
}
int SG_Grid_Cache_Get_Threshold(void)
{
return( gSG_Grid_Cache_Threshold );
}
double SG_Grid_Cache_Get_Threshold_MB(void)
{
return( (double)gSG_Grid_Cache_Threshold / (double)N_MEGABYTE_BYTES );
}
///////////////////////////////////////////////////////////
// //
// Memory //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool CSG_Grid::_Memory_Create(TSG_Grid_Memory_Type Memory_Type)
{
if( m_System.is_Valid() && m_Type > 0 && m_Type < GRID_TYPE_Count )
{
_Memory_Destroy();
Set_Buffer_Size(gSG_Grid_Cache_Threshold);
if( Memory_Type != GRID_MEMORY_Cache && gSG_Grid_Cache_bAutomatic && Get_NCells() * Get_nValueBytes() > gSG_Grid_Cache_Threshold )
{
switch( gSG_Grid_Cache_Confirm )
{
default:
Memory_Type = GRID_MEMORY_Cache;
break;
case 1:
{
CSG_String s;
s.Printf(SG_T("%s\n%s\n%s: %.2fMB"),
LNG("Shall I activate file caching for new grid."),
m_System.Get_Name(),
LNG("Total memory size"),
(Get_NCells() * Get_nValueBytes()) / (double)N_MEGABYTE_BYTES
);
if( SG_UI_Dlg_Continue(s, LNG("Activate Grid File Cache?")) )
{
Memory_Type = GRID_MEMORY_Cache;
}
}
break;
case 2:
{
CSG_Parameters p(NULL, LNG("Activate Grid File Cache?"), SG_T(""));
p.Add_Value(
NULL , SG_T("BUFFERSIZE") , LNG("Buffer Size [MB]"),
SG_T(""),
PARAMETER_TYPE_Double, SG_Grid_Cache_Get_Threshold_MB(), 0.0, true
);
if( SG_UI_Dlg_Parameters(&p, LNG("Activate Grid File Cache?")) )
{
Memory_Type = GRID_MEMORY_Cache;
Set_Buffer_Size((int)(p(SG_T("BUFFERSIZE"))->asDouble() * N_MEGABYTE_BYTES));
}
}
break;
}
}
//-------------------------------------------------
switch( Memory_Type )
{
case GRID_MEMORY_Normal:
return( _Array_Create() );
case GRID_MEMORY_Cache:
return( _Cache_Create() );
case GRID_MEMORY_Compression:
return( _Compr_Create() );
}
}
return( false );
}
//---------------------------------------------------------
void CSG_Grid::_Memory_Destroy(void)
{
Sort_Discard();
switch( m_Memory_Type )
{
case GRID_MEMORY_Normal: _Array_Destroy(); break;
case GRID_MEMORY_Cache: _Cache_Destroy(false); break;
case GRID_MEMORY_Compression: _Compr_Destroy(false); break;
}
_LineBuffer_Destroy();
m_Memory_Type = GRID_MEMORY_Normal;
}
///////////////////////////////////////////////////////////
// //
// LineBuffer //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
void CSG_Grid::_LineBuffer_Create(void)
{
_LineBuffer_Destroy();
LineBuffer = (TSG_Grid_Line *)SG_Malloc(LineBuffer_Count * sizeof(TSG_Grid_Line));
for(int i=0; i<LineBuffer_Count; i++)
{
LineBuffer[i].Data = (char *)SG_Malloc(_LineBuffer_Get_nBytes());
LineBuffer[i].y = -1;
LineBuffer[i].bModified = false;
}
}
//---------------------------------------------------------
void CSG_Grid::_LineBuffer_Destroy(void)
{
if( LineBuffer )
{
for(int i=0; i<LineBuffer_Count; i++)
{
if( LineBuffer[i].Data )
{
SG_Free(LineBuffer[i].Data);
}
}
SG_Free(LineBuffer);
LineBuffer = NULL;
}
}
//---------------------------------------------------------
bool CSG_Grid::Set_Buffer_Size(int Size)
{
int i;
if( m_System.is_Valid() && m_Type > 0 && m_Type < GRID_TYPE_Count )
{
Size /= _LineBuffer_Get_nBytes();
if( Size < 1 )
{
Size = 1;
}
else if( Size >= Get_NY() )
{
Size = Get_NY() - 1;
}
if( Size != LineBuffer_Count )
{
if( LineBuffer )
{
if( Size > LineBuffer_Count )
{
LineBuffer = (TSG_Grid_Line *)SG_Realloc(LineBuffer, Size * sizeof(TSG_Grid_Line));
for(i=LineBuffer_Count; i<Size; i++)
{
LineBuffer[i].Data = (char *)SG_Malloc(_LineBuffer_Get_nBytes());
LineBuffer[i].y = -1;
LineBuffer[i].bModified = false;
}
}
else
{
for(i=Size; i<LineBuffer_Count; i++)
{
if( LineBuffer[i].Data )
{
SG_Free(LineBuffer[i].Data);
}
}
LineBuffer = (TSG_Grid_Line *)SG_Realloc(LineBuffer, Size * sizeof(TSG_Grid_Line));
}
}
LineBuffer_Count = Size;
}
return( true );
}
return( false );
}
//---------------------------------------------------------
void CSG_Grid::_LineBuffer_Flush(void)
{
if( LineBuffer )
{
for(int i=0; i<LineBuffer_Count; i++)
{
switch( m_Memory_Type )
{
default:
break;
case GRID_MEMORY_Cache:
_Cache_LineBuffer_Save(LineBuffer + i);
break;
case GRID_MEMORY_Compression:
_Compr_LineBuffer_Save(LineBuffer + i);
break;
}
}
}
}
//---------------------------------------------------------
CSG_Grid::TSG_Grid_Line * CSG_Grid::_LineBuffer_Get_Line(int y) const
{
int i, iLine;
TSG_Grid_Line tmp_Line;
if( LineBuffer && y >= 0 && y < Get_NY() )
{
//-------------------------------------------------
if( y != LineBuffer[0].y )
{
for(i=1, iLine=0; i<LineBuffer_Count && !iLine; i++)
{
if( y == LineBuffer[i].y )
{
iLine = i;
}
}
//---------------------------------------------
if( !iLine )
{
iLine = LineBuffer_Count - 1;
switch( m_Memory_Type )
{
default:
break;
case GRID_MEMORY_Cache:
_Cache_LineBuffer_Save(LineBuffer + iLine);
_Cache_LineBuffer_Load(LineBuffer + iLine, y);
break;
case GRID_MEMORY_Compression:
_Compr_LineBuffer_Save(LineBuffer + iLine);
_Compr_LineBuffer_Load(LineBuffer + iLine, y);
break;
}
}
//---------------------------------------------
tmp_Line = LineBuffer[iLine];
for(i=iLine; i>0; i--)
{
LineBuffer[i] = LineBuffer[i - 1];
} // memmove(LineBuffer + 1, LineBuffer, (iLine - 1) * sizeof(TSG_Grid_Line));
LineBuffer[0] = tmp_Line;
}
//-------------------------------------------------
return( LineBuffer );
}
return( NULL );
}
//---------------------------------------------------------
void CSG_Grid::_LineBuffer_Set_Value(int x, int y, double Value)
{
TSG_Grid_Line *pLine;
if( (pLine = _LineBuffer_Get_Line(y)) != NULL )
{
switch( m_Type )
{
default:
break;
case GRID_TYPE_Byte:
((BYTE *)pLine->Data)[x] = (BYTE )Value;
break;
case GRID_TYPE_Char:
((char *)pLine->Data)[x] = (char )Value;
break;
case GRID_TYPE_Word:
((WORD *)pLine->Data)[x] = (WORD )Value;
break;
case GRID_TYPE_Short:
((short *)pLine->Data)[x] = (short )Value;
break;
case GRID_TYPE_DWord:
((DWORD *)pLine->Data)[x] = (DWORD )Value;
break;
case GRID_TYPE_Int:
((int *)pLine->Data)[x] = (int )Value;
break;
case GRID_TYPE_Float:
((float *)pLine->Data)[x] = (float )Value;
break;
case GRID_TYPE_Double:
((double *)pLine->Data)[x] = (double)Value;
break;
}
pLine->bModified = true;
}
}
//---------------------------------------------------------
double CSG_Grid::_LineBuffer_Get_Value(int x, int y) const
{
TSG_Grid_Line *pLine;
if( (pLine = _LineBuffer_Get_Line(y)) != NULL )
{
switch( m_Type )
{
default:
break;
case GRID_TYPE_Byte:
return( ((BYTE *)pLine->Data)[x] );
case GRID_TYPE_Char:
return( ((char *)pLine->Data)[x] );
case GRID_TYPE_Word:
return( ((WORD *)pLine->Data)[x] );
case GRID_TYPE_Short:
return( ((short *)pLine->Data)[x] );
case GRID_TYPE_DWord:
return( ((DWORD *)pLine->Data)[x] );
case GRID_TYPE_Int:
return( ((int *)pLine->Data)[x] );
case GRID_TYPE_Float:
return( ((float *)pLine->Data)[x] );
case GRID_TYPE_Double:
return( ((double *)pLine->Data)[x] );
}
}
return( 0.0 );
}
///////////////////////////////////////////////////////////
// //
// Array //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool CSG_Grid::_Array_Create(void)
{
if( m_System.is_Valid() && m_Type > 0 && m_Type < GRID_TYPE_Count )
{
_Array_Destroy();
m_Values = (void **)SG_Malloc(Get_NY() * sizeof(void *));
for(int y=0; y<Get_NY(); y++)
{
m_Values[y] = (void *)SG_Calloc(1, _Get_nLineBytes());
}
return( true );
}
return( false );
}
//---------------------------------------------------------
void CSG_Grid::_Array_Destroy(void)
{
if( m_Values )
{
for(int y=0; y<Get_NY(); y++)
{
if( m_Values[y] )
{
SG_Free(m_Values[y]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -