1 /**********************************************************
2 * Version $Id$
3 *********************************************************/
4 /*******************************************************************************
5 QueryBuilder.cpp
6 Copyright (C) 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 A 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 "QueryBuilder.h"
31
32
33 ///////////////////////////////////////////////////////////
34 // //
35 // //
36 // //
37 ///////////////////////////////////////////////////////////
38
39 //---------------------------------------------------------
CSelect_Numeric(void)40 CSelect_Numeric::CSelect_Numeric(void)
41 {
42 //-----------------------------------------------------
43 Set_Name (_TL("Select by Attributes... (Numerical Expression)"));
44
45 Set_Author ("V.Olaya (c) 2004, O.Conrad (c) 2011");
46
47 Set_Description(_TW(
48 "Selects records for which the expression evaluates to non-zero. "
49 "The expression syntax is the same as the one for the table calculator. "
50 "If an attribute field is selected, the expression evaluates only "
51 "this attribute, which can be addressed with the letter 'a' in the "
52 "expression formula. If no attribute is selected, attributes are addressed "
53 "by the character 'f' (for 'field') followed by the field number "
54 "(i.e.: f1, f2, ..., fn) or by the field name in square brackets "
55 "(e.g.: [Field Name]).\n"
56 "Examples:\n"
57 "- f1 > f2\n"
58 "- eq([Population] * 2, [Area])\n"
59 ));
60
61 //-----------------------------------------------------
62 Parameters.Add_Shapes("",
63 "SHAPES" , _TL("Shapes"),
64 _TL(""),
65 PARAMETER_INPUT
66 );
67
68 Parameters.Add_Table_Field("SHAPES",
69 "FIELD" , _TL("Attribute"),
70 _TL("attribute to be evaluated by expression ('a'); if not set all attributes can be addressed (f1, f2, ..., fn)."),
71 true
72 );
73
74 Parameters.Add_String("",
75 "EXPRESSION", _TL("Expression"),
76 _TL(""),
77 "a > 0"
78 );
79
80 Parameters.Add_Bool("",
81 "USE_NODATA", _TL("Use No-Data"),
82 _TL(""),
83 false
84 );
85
86 Parameters.Add_Choice("",
87 "METHOD" , _TL("Method"),
88 _TL(""),
89 CSG_String::Format("%s|%s|%s|%s",
90 _TL("new selection"),
91 _TL("add to current selection"),
92 _TL("select from current selection"),
93 _TL("remove from current selection")
94 ), 0
95 );
96 }
97
98
99 ///////////////////////////////////////////////////////////
100 // //
101 ///////////////////////////////////////////////////////////
102
103 //---------------------------------------------------------
On_Execute(void)104 bool CSelect_Numeric::On_Execute(void)
105 {
106 CSG_Table *pTable = Parameters("SHAPES")->asShapes();
107
108 if( pTable->Get_Count() < 1 || pTable->Get_Field_Count() < 1 )
109 {
110 Error_Set(_TL("empty or invalid shapes layer"));
111
112 return( false );
113 }
114
115 //-----------------------------------------------------
116 CSG_Array_Int Fields;
117
118 CSG_Formula Formula;
119
120 if( !Formula.Set_Formula(Get_Formula(Parameters("EXPRESSION")->asString(), pTable, Fields)) )
121 {
122 CSG_String Message;
123
124 if( Formula.Get_Error(Message) )
125 {
126 Error_Set(Message);
127 }
128
129 return( false );
130 }
131
132 //-----------------------------------------------------
133 int Method = Parameters("METHOD")->asInt();
134
135 bool bUseNoData = Parameters("USE_NODATA")->asBool();
136
137 CSG_Vector Values((int)Fields.Get_Size());
138
139 //-----------------------------------------------------
140 for(int i=0; i<pTable->Get_Count() && Set_Progress(i, pTable->Get_Count()); i++)
141 {
142 CSG_Table_Record *pRecord = pTable->Get_Record(i);
143
144 bool bOkay = true;
145
146 for(size_t Field=0; bOkay && Field<Fields.Get_Size(); Field++)
147 {
148 if( (bOkay = bUseNoData || !pRecord->is_NoData(Fields[Field])) == true )
149 {
150 Values[Field] = pRecord->asDouble(Fields[Field]);
151 }
152 }
153
154 //-------------------------------------------------
155 if( bOkay )
156 {
157 switch( Method )
158 {
159 default: // New selection
160 if( ( pRecord->is_Selected() && !Formula.Get_Value(Values))
161 || (!pRecord->is_Selected() && Formula.Get_Value(Values)) )
162 {
163 pTable->Select(i, true);
164 }
165 break;
166
167 case 1: // Add to current selection
168 if( !pRecord->is_Selected() && Formula.Get_Value(Values) )
169 {
170 pTable->Select(i, true);
171 }
172 break;
173
174 case 2: // Select from current selection
175 if( pRecord->is_Selected() && !Formula.Get_Value(Values) )
176 {
177 pTable->Select(i, true);
178 }
179 break;
180
181 case 3: // Remove from current selection
182 if( pRecord->is_Selected() && Formula.Get_Value(Values) )
183 {
184 pTable->Select(i, true);
185 }
186 break;
187 }
188 }
189 }
190
191 //-----------------------------------------------------
192 Message_Fmt("\n%s: %d", _TL("selected shapes"), pTable->Get_Selection_Count());
193
194 DataObject_Update(pTable);
195
196 return( true );
197 }
198
199
200 ///////////////////////////////////////////////////////////
201 // //
202 ///////////////////////////////////////////////////////////
203
204 //---------------------------------------------------------
Get_Formula(CSG_String Formula,CSG_Table * pTable,CSG_Array_Int & Fields)205 CSG_String CSelect_Numeric::Get_Formula(CSG_String Formula, CSG_Table *pTable, CSG_Array_Int &Fields)
206 {
207 const SG_Char vars[27] = SG_T("abcdefghijklmnopqrstuvwxyz");
208
209 Fields.Destroy();
210
211 int Field = Parameters("FIELD")->asInt();
212
213 if( Field >= 0 )
214 {
215 // Formula.Replace("a", CSG_String(vars[Fields.Get_Size()]));
216
217 Fields += Field;
218
219 return( Formula );
220 }
221
222 //---------------------------------------------------------
223 for(Field=pTable->Get_Field_Count()-1; Field>=0 && Fields.Get_Size()<26; Field--)
224 {
225 bool bUse = false;
226
227 CSG_String s;
228
229 s.Printf("f%d", Field + 1);
230
231 if( Formula.Find(s) >= 0 )
232 {
233 Formula.Replace(s, CSG_String(vars[Fields.Get_Size()]));
234
235 bUse = true;
236 }
237
238 s.Printf("F%d", Field + 1);
239
240 if( Formula.Find(s) >= 0 )
241 {
242 Formula.Replace(s, CSG_String(vars[Fields.Get_Size()]));
243
244 bUse = true;
245 }
246
247 s.Printf("[%s]", pTable->Get_Field_Name(Field));
248
249 if( Formula.Find(s) >= 0 )
250 {
251 Formula.Replace(s, CSG_String(vars[Fields.Get_Size()]));
252
253 bUse = true;
254 }
255
256 if( bUse )
257 {
258 Fields += Field;
259 }
260 }
261
262 return( Formula );
263 }
264
265
266 ///////////////////////////////////////////////////////////
267 // //
268 // //
269 // //
270 ///////////////////////////////////////////////////////////
271
272 //---------------------------------------------------------
273