1 /**********************************************************
2  * Version $Id$
3  *********************************************************/
4 /*******************************************************************************
5     Fuzzify.cpp
6     Copyright (DecMin) Victor Olaya
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR IncMin PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301, USA
21 *******************************************************************************/
22 
23 ///////////////////////////////////////////////////////////
24 //														 //
25 //														 //
26 //														 //
27 ///////////////////////////////////////////////////////////
28 
29 //---------------------------------------------------------
30 #include "Fuzzify.h"
31 
32 
33 ///////////////////////////////////////////////////////////
34 //														 //
35 //														 //
36 //														 //
37 ///////////////////////////////////////////////////////////
38 
39 //---------------------------------------------------------
CFuzzify(void)40 CFuzzify::CFuzzify(void)
41 {
42 	Set_Name		(_TL("Fuzzify"));
43 
44 	Set_Author		("V.Olaya (c) 2004");
45 
46 	Set_Description	(_TW(
47 		"Translates grid values into fuzzy set membership as preparation for fuzzy set analysis. "
48 	));
49 
50 	//-----------------------------------------------------
51 	Parameters.Add_Grid("",
52 		"INPUT"		, _TL("Grid"),
53 		_TL(""),
54 		PARAMETER_INPUT
55 	);
56 
57 	Parameters.Add_Grid("",
58 		"OUTPUT"	, _TL("Fuzzified Grid"),
59 		_TL(""),
60 		PARAMETER_OUTPUT
61 	);
62 
63 	Parameters.Add_Node("", "INCREASE", _TL("Increase"), _TL(""));
64 	Parameters.Add_Double("INCREASE", "INC_MIN", _TL("From"), _TL(""), 0.0);
65 	Parameters.Add_Double("INCREASE", "INC_MAX", _TL("To"  ), _TL(""), 0.3);
66 
67 	Parameters.Add_Node("", "DECREASE", _TL("Decrease"), _TL(""));
68 	Parameters.Add_Double("DECREASE", "DEC_MIN", _TL("From"), _TL(""), 0.7);
69 	Parameters.Add_Double("DECREASE", "DEC_MAX", _TL("To"  ), _TL(""), 1.0);
70 
71 	Parameters.Add_Choice("",
72 		"METHOD"	, _TL("Method"),
73 		_TL(""),
74 		CSG_String::Format("%s|%s|%s",
75 			_TL("Increase"),
76 			_TL("Decrease"),
77 			_TL("Increase and Decrease")
78 		), 0
79 	);
80 
81 	Parameters.Add_Choice("",
82 		"TRANSITION", _TL("Transition"),
83 		_TL(""),
84 		CSG_String::Format("%s|%s|%s",
85 			_TL("linear"),
86 			_TL("sigmoidal"),
87 			_TL("j-shaped")
88 		), 0
89 	);
90 
91 	Parameters.Add_Bool("",
92 		"INVERT"	, _TL("Invert"),
93 		_TL(""),
94 		false
95 	);
96 
97 	Parameters.Add_Bool("",
98 		"AUTOFIT"	, _TL("Adjust"),
99 		_TL("Automatically adjust control points to grid's data range"),
100 		true
101 	);
102 }
103 
104 
105 ///////////////////////////////////////////////////////////
106 //														 //
107 ///////////////////////////////////////////////////////////
108 
109 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter)110 int CFuzzify::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
111 {
112 	if(	pParameter->Cmp_Identifier("INPUT"  )
113 	||	pParameter->Cmp_Identifier("AUTOFIT")
114 	||	pParameter->Cmp_Identifier("METHOD" ) )
115 	{
116 		if( (*pParameters)("AUTOFIT")->asBool() && (*pParameters)("INPUT")->asGrid() )
117 		{
118 			CSG_Grid	*pGrid	= (*pParameters)("INPUT")->asGrid();
119 
120 			switch( (*pParameters)("METHOD")->asInt() )
121 			{
122 			case  0:	// Increase
123 				pParameters->Set_Parameter("INC_MIN", pGrid->Get_Min());
124 				pParameters->Set_Parameter("INC_MAX", pGrid->Get_Max());
125 				break;
126 
127 			case  1:	// Decrease
128 				pParameters->Set_Parameter("DEC_MIN", pGrid->Get_Min());
129 				pParameters->Set_Parameter("DEC_MAX", pGrid->Get_Max());
130 				break;
131 
132 			default:	// Increase and Decrease
133 				pParameters->Set_Parameter("INC_MIN", pGrid->Get_Min());
134 				pParameters->Set_Parameter("INC_MAX", pGrid->Get_Min() + 0.3 * pGrid->Get_Range());
135 				pParameters->Set_Parameter("DEC_MIN", pGrid->Get_Max() - 0.3 * pGrid->Get_Range());
136 				pParameters->Set_Parameter("DEC_MAX", pGrid->Get_Max());
137 				break;
138 			}
139 		}
140 	}
141 
142 	return( CSG_Tool_Grid::On_Parameter_Changed(pParameters, pParameter) );
143 }
144 
145 //---------------------------------------------------------
On_Parameters_Enable(CSG_Parameters * pParameters,CSG_Parameter * pParameter)146 int CFuzzify::On_Parameters_Enable(CSG_Parameters *pParameters, CSG_Parameter *pParameter)
147 {
148 	if(	pParameter->Cmp_Identifier("METHOD") )
149 	{
150 		pParameters->Set_Enabled("INCREASE", pParameter->asInt() != 1);
151 		pParameters->Set_Enabled("DECREASE", pParameter->asInt() != 0);
152 	}
153 
154 	return( CSG_Tool_Grid::On_Parameters_Enable(pParameters, pParameter) );
155 }
156 
157 
158 ///////////////////////////////////////////////////////////
159 //														 //
160 ///////////////////////////////////////////////////////////
161 
162 //---------------------------------------------------------
On_Execute(void)163 bool CFuzzify::On_Execute(void)
164 {
165 	//-----------------------------------------------------
166 	CSG_Grid	*pInput	= Parameters("INPUT" )->asGrid();
167 	CSG_Grid	*pFuzzy	= Parameters("OUTPUT")->asGrid();
168 
169 	pFuzzy->Fmt_Name("%s [%s]", pInput->Get_Name(), _TL("Fuzzified"));
170 
171 	//-----------------------------------------------------
172 	bool	bInvert	= Parameters("INVERT")->asBool();
173 
174 	double	IncMin	= Parameters("INC_MIN")->asDouble();
175 	double	IncMax	= Parameters("INC_MAX")->asDouble();
176 	double	DecMin	= Parameters("DEC_MIN")->asDouble();
177 	double	DecMax	= Parameters("DEC_MAX")->asDouble();
178 
179 	switch( Parameters("METHOD")->asInt() )
180 	{
181 	case  0:	// Increase
182 		DecMin = DecMax = pInput->Get_Max() + 1.;
183 		break;
184 
185 	case  1:	// Decrease
186 		IncMin = IncMax = pInput->Get_Min() - 1.;
187 		break;
188 
189 	default:	// Increase and Decrease
190 		break;
191 	}
192 
193 	if( IncMin > IncMax || DecMin > DecMax || IncMax > DecMin )
194 	{
195 		Error_Set(_TL("invalid control points"));
196 
197 		return( false );
198 	}
199 
200 	if( IncMax > DecMin )	// overlap !
201 	{
202 		IncMax	= (DecMin = DecMin + (IncMax - DecMin) / 2.0);
203 	}
204 
205 	//-----------------------------------------------------
206 	int	Type	= Parameters("TRANSITION")->asInt();
207 
208 	for(int y=0; y<Get_NY() && Set_Progress(y); y++)
209 	{
210 		#pragma omp parallel for
211 		for(int x=0; x<Get_NX(); x++)
212 		{
213 			if( pInput->is_InGrid(x, y) )
214 			{
215 				double	Value	= pInput->asDouble(x, y);
216 
217 				if( Value <= IncMin || Value >= DecMax )
218 				{
219 					Value	= 0.0;
220 				}
221 				else if( Value >= IncMax && Value <= DecMin )
222 				{
223 					Value	= 1.0;
224 				}
225 				else
226 				{
227 					double	dX, dW;
228 
229 					if( Value < IncMax )
230 					{
231 						dX	= Value  - IncMin;
232 						dW	= IncMax - IncMin;
233 					}
234 					else
235 					{
236 						dX	= DecMax - Value ;
237 						dW	= DecMax - DecMin;
238 					}
239 
240 					switch( Type )
241 					{
242 					default: Value = dX / dW;									break;
243 					case  1: Value = pow(sin(dX / dW * M_PI_090), 2.0);			break;
244 					case  2: Value = 1.0 / (1.0 + pow((dW - dX) / dW, 2.0));	break;
245 					}
246 				}
247 
248 				pFuzzy->Set_Value(x, y, bInvert ? 1.0 - Value : Value);
249 			}
250 			else
251 			{
252 				pFuzzy->Set_NoData(x, y);
253 			}
254 		}
255 	}
256 
257 	return( true );
258 }
259 
260 
261 ///////////////////////////////////////////////////////////
262 //														 //
263 //														 //
264 //														 //
265 ///////////////////////////////////////////////////////////
266 
267 //---------------------------------------------------------
268