📄 grid_cluster_analysis.cpp
字号:
///////////////////////////////////////////////////////////
// //
// SAGA //
// //
// System for Automated Geoscientific Analyses //
// //
// Module Library: //
// Grid_Discretisation //
// //
//-------------------------------------------------------//
// //
// Grid_Cluster_Analysis.cpp //
// //
// Copyright (C) 2003 by //
// Olaf Conrad //
// //
//-------------------------------------------------------//
// //
// This file is part of 'SAGA - System for Automated //
// Geoscientific Analyses'. SAGA is free software; you //
// can redistribute it and/or modify it under the terms //
// of the GNU General Public License as published by the //
// Free Software Foundation; version 2 of the License. //
// //
// SAGA 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 General Public //
// License for more details. //
// //
// You should have received a copy of the GNU 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. //
// //
//-------------------------------------------------------//
// //
// e-mail: oconrad@saga-gis.org //
// //
// contact: Olaf Conrad //
// Institute of Geography //
// University of Goettingen //
// Goldschmidtstr. 5 //
// 37077 Goettingen //
// Germany //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
#include "Grid_Cluster_Analysis.h"
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
CGrid_Cluster_Analysis::CGrid_Cluster_Analysis(void)
{
//-----------------------------------------------------
// 1. Info...
Set_Name (_TL("Cluster Analysis for Grids"));
Set_Author (_TL("Copyrights (c) 2001 by Olaf Conrad"));
Set_Description (_TW(
"Cluster Analysis for grids.\n\nReferences:\n\n"
"Iterative Minimum Distance:\n"
"- Forgy, E. (1965):\n"
" 'Cluster Analysis of multivariate data: efficiency vs. interpretability of classifications',\n"
" Biometrics 21:768\n\n"
"Hill-Climbing:"
"- Rubin, J. (1967):\n"
" 'Optimal Classification into Groups: An Approach for Solving the Taxonomy Problem',\n"
" J. Theoretical Biology, 15:103-144\n\n"
));
//-----------------------------------------------------
// 2. Grids...
Parameters.Add_Grid_List(
NULL , "INPUT" , _TL("Grids"),
_TL(""),
PARAMETER_INPUT
);
Parameters.Add_Grid(
NULL , "RESULT" , _TL("Clusters"),
_TL(""),
PARAMETER_OUTPUT, true, GRID_TYPE_Int
);
Parameters.Add_Table(
NULL , "STATISTICS" , _TL("Statistics"),
_TL(""),
PARAMETER_OUTPUT
);
//-----------------------------------------------------
// 3. General Parameters...
Parameters.Add_Choice(
NULL , "METHOD" , _TL("Method"),
_TL(""),
CSG_String::Format(SG_T("%s|%s|%s|"),
_TL("Iterative Minimum Distance (Forgy 1965)"),
_TL("Hill-Climbing (Rubin 1967)"),
_TL("Combined Minimum Distance / Hillclimbing")
),1
);
Parameters.Add_Value(
NULL , "NCLUSTER" , _TL("Clusters"),
_TL("Number of clusters"),
PARAMETER_TYPE_Int, 10, 2, true
);
Parameters.Add_Value(
NULL , "NORMALISE" , _TL("Normalise"),
_TL("Automatically normalise grids by standard deviation before clustering."),
PARAMETER_TYPE_Bool, true
);
Parameters.Add_Value(
NULL , "UPDATEVIEW" , _TL("Update View"),
_TL("Update cluster view while clustering."),
PARAMETER_TYPE_Bool, true
);
}
//---------------------------------------------------------
CGrid_Cluster_Analysis::~CGrid_Cluster_Analysis(void)
{}
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
bool CGrid_Cluster_Analysis::On_Execute(void)
{
int i, j, nCluster;
long nElements;
double SP;
CSG_Parameter_Grid_List *pGrids;
//-----------------------------------------------------
pGrids = Parameters("INPUT") ->asGridList();
nGrids = pGrids->Get_Count();
pCluster = Parameters("RESULT") ->asGrid();
nCluster = Parameters("NCLUSTER")->asInt();
//-----------------------------------------------------
if( nGrids > 0 )
{
Grids = (CSG_Grid **)SG_Malloc(nGrids * sizeof(CSG_Grid *));
if( Parameters("NORMALISE")->asBool() )
{
for(i=0; i<nGrids; i++)
{
Grids[i] = SG_Create_Grid(pGrids->asGrid(i), GRID_TYPE_Float);
Grids[i]->Assign(pGrids->asGrid(i));
Grids[i]->Normalise();
}
}
else
{
for(i=0; i<nGrids; i++)
{
Grids[i] = pGrids->asGrid(i);
}
}
pCluster->Assign(-1);
nMembers = (int *)SG_Malloc(nCluster * sizeof(int));
Variances = (double *)SG_Malloc(nCluster * sizeof(double));
Centroids = (double **)SG_Malloc(nCluster * sizeof(double *));
for(i=0; i<nCluster; i++)
{
Centroids[i] = (double *)SG_Malloc(nGrids * sizeof(double));
}
//-------------------------------------------------
nElements = Get_NCells();
switch( Parameters("METHOD")->asInt() )
{
case 0:
SP = MinimumDistance (nElements, nCluster);
break;
case 1:
SP = HillClimbing (nElements, nCluster);
break;
case 2:
SP = MinimumDistance (nElements, nCluster);
nElements = Get_NCells(); // may have been diminished because of no data values...
SP = HillClimbing (nElements, nCluster);
break;
}
//-------------------------------------------------
if( Parameters("NORMALISE")->asBool() )
{
for(i=0; i<nGrids; i++)
{
delete(Grids[i]);
Grids[i] = pGrids->asGrid(i);
}
for(i=0; i<nGrids; i++)
{
for(j=0; j<nCluster; j++)
{
Centroids[j][i] = sqrt(Grids[i]->Get_Variance()) * Centroids[j][i] + Grids[i]->Get_ArithMean();
}
}
}
Write_Result(Parameters("STATISTICS")->asTable(), nElements, nCluster, SP);
SG_Free(Grids);
for(i=0; i<nCluster; i++)
{
SG_Free(Centroids[i]);
}
SG_Free(Centroids);
SG_Free(Variances);
SG_Free(nMembers);
return( true );
}
return( false );
}
///////////////////////////////////////////////////////////
// //
// //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
void CGrid_Cluster_Analysis::Write_Result(CSG_Table *pTable, long nElements, int nCluster, double SP)
{
int i, j;
CSG_String s;
CSG_Table_Record *pRecord;
pTable->Destroy();
pTable->Set_Name(_TL("Cluster Analysis"));
pTable->Add_Field(_TL("ClusterID") , TABLE_FIELDTYPE_Int);
pTable->Add_Field(_TL("Elements") , TABLE_FIELDTYPE_Int);
pTable->Add_Field(_TL("Variance") , TABLE_FIELDTYPE_Double);
s.Printf(SG_T("\n%s:\t%ld \n%s:\t%d \n%s:\t%d \n%s:\t%f"),
_TL("Number of Elements") , nElements,
_TL("\nNumber of Variables") , nGrids,
_TL("\nNumber of Clusters") , nCluster,
_TL("\nValue of Target Function") , SP
);
s.Append(CSG_String::Format(SG_T("%s\t%s\t%s"), _TL("Cluster"), _TL("Elements"), _TL("Variance")));
for(j=0; j<nGrids; j++)
{
s.Append(CSG_String::Format(SG_T("\t%02d_%s"), j + 1, Grids[j]->Get_Name()));
pTable->Add_Field(Grids[j]->Get_Name(), TABLE_FIELDTYPE_Double);
}
Message_Add(s);
for(i=0; i<nCluster; i++)
{
s.Printf(SG_T("%d\t%d\t%f"), i, nMembers[i], Variances[i]);
pRecord = pTable->Add_Record();
pRecord->Set_Value(0, i);
pRecord->Set_Value(1, nMembers[i]);
pRecord->Set_Value(2, Variances[i]);
for(j=0; j<nGrids; j++)
{
s.Append(CSG_String::Format(SG_T("\t%f"), Centroids[i][j]));
pRecord->Set_Value(j + 3, Centroids[i][j]);
}
Message_Add(s);
}
}
///////////////////////////////////////////////////////////
// //
// Minimum Distance //
// //
///////////////////////////////////////////////////////////
//---------------------------------------------------------
// (nElements)-Array -> Bei Eingabe Startgruppierung oder 0.
// Bei Ausgabe Gruppierung: >Das ite Element ist im Cluster Cluster(i).
double CGrid_Cluster_Analysis::MinimumDistance(long &nElements, int nCluster)
{
//-----------------------------------------------------
// Variablen...
bool bContinue;
int iElement, iGrid, iCluster, nClusterElements, nShifts, minCluster, nPasses;
double d, Variance, minVariance, SP, SP_Last = -1;
//-----------------------------------------------------
// Anfangspartition (Standard falls nicht vorgegeben
for(iElement=0, nClusterElements=0; iElement<nElements; iElement++)
{
for(iGrid=0, bContinue=true; iGrid<nGrids && bContinue; iGrid++)
{
if( Grids[iGrid]->is_NoData(iElement) )
{
bContinue = false;
}
}
if( bContinue )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -