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