1 
2 /*******************************************************************************
3     Grid_CVA.cpp
4     Copyright (C) Victor Olaya
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA
19 *******************************************************************************/
20 
21 ///////////////////////////////////////////////////////////
22 //                                                       //
23 //                                                       //
24 //                                                       //
25 ///////////////////////////////////////////////////////////
26 
27 //---------------------------------------------------------
28 #include "Grid_CVA.h"
29 
30 
31 ///////////////////////////////////////////////////////////
32 //                                                       //
33 //                                                       //
34 //                                                       //
35 ///////////////////////////////////////////////////////////
36 
37 //---------------------------------------------------------
CGrid_CVA(void)38 CGrid_CVA::CGrid_CVA(void)
39 {
40 	Set_Name		(_TL("Change Vector Analysis"));
41 
42 	Set_Author		("V.Olaya (c) 2004, O.Conrad (c) 2012");
43 
44 	Set_Description	(_TW(
45 		"This tool performs a change vector analysis (CVA) for the given input features. "
46 		"Input features are supplied as grid lists for initial and final state. "
47 		"In both lists features have to be given in the same order. "
48 		"Distance is measured as Euclidean distance in features space. When analyzing two features "
49 		"direction is calculated as angle (radians) by default. Otherwise direction is coded as "
50 		"the quadrant it points to in terms of feature space. "
51 	));
52 
53 	Parameters.Add_Grid_List("",
54 		"A"		, _TL("Initial State"),
55 		_TL(""),
56 		PARAMETER_INPUT
57 	);
58 
59 	Parameters.Add_Grid_List("",
60 		"B"		, _TL("Final State"),
61 		_TL(""),
62 		PARAMETER_INPUT
63 	);
64 
65 	Parameters.Add_Grid("",
66 		"DIST"	, _TL("Distance"),
67 		_TL(""),
68 		PARAMETER_OUTPUT
69 	);
70 
71 	Parameters.Add_Grid("",
72 		"DIR"	, _TL("Angle"),
73 		_TL(""),
74 		PARAMETER_OUTPUT_OPTIONAL
75 	);
76 
77 	Parameters.Add_Grids("",
78 		"C"		, _TL("Change Vector"),
79 		_TL(""),
80 		PARAMETER_OUTPUT_OPTIONAL
81 	);
82 }
83 
84 
85 ///////////////////////////////////////////////////////////
86 //                                                       //
87 ///////////////////////////////////////////////////////////
88 
89 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)90 int CGrid_CVA::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
91 {
92 	if(	pParameter->Cmp_Identifier("A")
93 	||	pParameter->Cmp_Identifier("B") )
94 	{
95 		pParameters->Set_Enabled("ANGLE",
96 				(*pParameters)("A")->asInt() == 2
97 			&&	(*pParameters)("B")->asInt() == 2
98 		);
99 	}
100 
101 	return( CSG_Tool_Grid::On_Parameters_Enable(pParameters, pParameter) );
102 }
103 
104 
105 ///////////////////////////////////////////////////////////
106 //                                                       //
107 ///////////////////////////////////////////////////////////
108 
109 //---------------------------------------------------------
On_Execute(void)110 bool CGrid_CVA::On_Execute(void)
111 {
112 	CSG_Parameter_Grid_List	*pA	= Parameters("A")->asGridList();
113 	CSG_Parameter_Grid_List	*pB	= Parameters("B")->asGridList();
114 
115 	int	nFeatures	= pA->Get_Grid_Count();
116 
117 	if( nFeatures != pB->Get_Grid_Count() )
118 	{
119 		Error_Set(_TL("number of initial and final state grids differs"));
120 
121 		return( false );
122 	}
123 
124 	if( nFeatures == 0 )
125 	{
126 		Error_Set(_TL("no grids in list"));
127 
128 		return( false );
129 	}
130 
131 	//-----------------------------------------------------
132 	CSG_Grids	*pC	= Parameters("C")->asGrids();
133 
134 	if( pC )
135 	{
136 		if( !pC->Create(Get_System(), nFeatures) || !pC->is_Valid() || pC->Get_NZ() < nFeatures )
137 		{
138 			pC	= NULL;
139 		}
140 		else
141 		{
142 			pC->Set_Name(_TL("Change Vector"));
143 
144 			pC->Add_Attribute("A", SG_DATATYPE_String);
145 			pC->Add_Attribute("B", SG_DATATYPE_String);
146 
147 			for(int i=0; i<nFeatures; i++)
148 			{
149 				pC->Set_Z(i, i + 1);
150 
151 				pC->Get_Attributes()[i].Set_Value(1, pA->Get_Grid(i)->Get_Name());
152 				pC->Get_Attributes()[i].Set_Value(2, pB->Get_Grid(i)->Get_Name());
153 			}
154 
155 			pC->Get_Attributes_Ptr()->Set_Field_Type(0, SG_DATATYPE_Word);
156 		}
157 	}
158 
159 	//-----------------------------------------------------
160 	CSG_Colors	Colors;
161 	Colors.Set_Ramp(SG_GET_RGB(255, 255, 255), SG_GET_RGB(  0, 127, 127), 0, Colors.Get_Count() / 2);
162 	Colors.Set_Ramp(SG_GET_RGB(  0, 127, 127), SG_GET_RGB(255,   0,   0),    Colors.Get_Count() / 2, Colors.Get_Count());
163 
164 	CSG_Grid	*pLength = Parameters("DIST")->asGrid();
165 	CSG_Grid	*pAngle  = Parameters("DIR" )->asGrid();
166 
167 	DataObject_Set_Colors(pLength, Colors);
168 	DataObject_Set_Colors(pAngle , Colors);
169 
170 	//-----------------------------------------------------
171     for(int y=0; y<Get_NY() && Set_Progress(y); y++)
172 	{
173 		#pragma omp parallel for
174 		for(int x=0; x<Get_NX(); x++)
175 		{
176 			bool	bOkay	= true;	CSG_Vector	a(nFeatures), b(nFeatures);
177 
178 			for(int i=0; bOkay && i<nFeatures; i++)
179 			{
180 				if( (bOkay = !pA->Get_Grid(i)->is_NoData(x, y) && !pB->Get_Grid(i)->is_NoData(x, y)) == true )
181 				{
182 					a[i]	= pA->Get_Grid(i)->asDouble(x, y);
183 					b[i]	= pB->Get_Grid(i)->asDouble(x, y);
184 				}
185 			}
186 
187 			//---------------------------------------------
188 			if( bOkay == false )
189 			{
190 				if( pLength ) pLength->Set_NoData(x, y);
191 				if( pAngle  ) pAngle ->Set_NoData(x, y);
192 
193 				for(int i=0; pC && i<nFeatures; i++)
194 				{
195 					pC->Set_NoData(x, y, i);
196 				}
197 			}
198 			else
199 			{
200 				CSG_Vector	c	= b - a;
201 
202 				if( pLength ) pLength->Set_Value(x, y, c.Get_Length());
203 				if( pAngle  ) pAngle ->Set_Value(x, y, a.Get_Angle(b) * M_RAD_TO_DEG);
204 
205 				for(int i=0; pC && i<nFeatures; i++)
206 				{
207 					pC->Set_Value(x, y, i, c[i]);
208 				}
209 			}
210         }
211     }
212 
213 	//-----------------------------------------------------
214 	return( true );
215 }
216 
217 
218 ///////////////////////////////////////////////////////////
219 //                                                       //
220 //                                                       //
221 //                                                       //
222 ///////////////////////////////////////////////////////////
223 
224 //---------------------------------------------------------
225