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