1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //                    User Interface                     //
9 //                                                       //
10 //                    Program: SAGA                      //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                    WKSP_Grid.cpp                      //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'. SAGA is free software; you   //
22 // can redistribute it and/or modify it under the terms  //
23 // of the GNU General Public License as published by the //
24 // Free Software Foundation, either version 2 of the     //
25 // License, or (at your option) any later version.       //
26 //                                                       //
27 // SAGA is distributed in the hope that it will be       //
28 // useful, but WITHOUT ANY WARRANTY; without even the    //
29 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
30 // PARTICULAR PURPOSE. See the GNU General Public        //
31 // License for more details.                             //
32 //                                                       //
33 // You should have received a copy of the GNU General    //
34 // Public License along with this program; if not, see   //
35 // <http://www.gnu.org/licenses/>.                       //
36 //                                                       //
37 //-------------------------------------------------------//
38 //                                                       //
39 //    contact:    Olaf Conrad                            //
40 //                Institute of Geography                 //
41 //                University of Goettingen               //
42 //                Goldschmidtstr. 5                      //
43 //                37077 Goettingen                       //
44 //                Germany                                //
45 //                                                       //
46 //    e-mail:     oconrad@saga-gis.org                   //
47 //                                                       //
48 ///////////////////////////////////////////////////////////
49 
50 //---------------------------------------------------------
51 #include <wx/dc.h>
52 #include <wx/dcmemory.h>
53 #include <wx/image.h>
54 #include <wx/filename.h>
55 #include <wx/clipbrd.h>
56 
57 #include <saga_gdi/sgdi_helper.h>
58 
59 #include "res_commands.h"
60 #include "res_dialogs.h"
61 
62 #include "helper.h"
63 
64 #include "active.h"
65 #include "active_attributes.h"
66 
67 #include "wksp_map_control.h"
68 
69 #include "wksp_layer_classify.h"
70 #include "wksp_layer_legend.h"
71 
72 #include "wksp_data_manager.h"
73 #include "wksp_grid_manager.h"
74 #include "wksp_grid.h"
75 #include "wksp_grids.h"
76 
77 #include "data_source_pgsql.h"
78 
79 
80 ///////////////////////////////////////////////////////////
81 //														 //
82 //														 //
83 //														 //
84 ///////////////////////////////////////////////////////////
85 
86 //---------------------------------------------------------
CWKSP_Grid(CSG_Grid * pGrid)87 CWKSP_Grid::CWKSP_Grid(CSG_Grid *pGrid)
88 	: CWKSP_Layer(pGrid)
89 {
90 	m_Edit_Attributes.Add_Field("ROW", SG_DATATYPE_Int);
91 
92 	On_Create_Parameters();
93 
94 	DataObject_Changed();
95 }
96 
97 
98 ///////////////////////////////////////////////////////////
99 //														 //
100 ///////////////////////////////////////////////////////////
101 
102 //---------------------------------------------------------
Get_Description(void)103 wxString CWKSP_Grid::Get_Description(void)
104 {
105 	wxString	s;
106 
107 	//-----------------------------------------------------
108 	s	+= wxString::Format("<h4>%s</h4>", _TL("Grid"));
109 
110 	s	+= "<table border=\"0\">";
111 
112 	DESC_ADD_STR (_TL("Name"               ), m_pObject->Get_Name());
113 	DESC_ADD_STR (_TL("Description"        ), m_pObject->Get_Description());
114 
115 	if( SG_File_Exists(m_pObject->Get_File_Name(false)) )
116 	{
117 		DESC_ADD_STR (_TL("File"           ), m_pObject->Get_File_Name(false));
118 
119 		if( m_pObject->Get_MetaData()("GDAL_DRIVER") )
120 			DESC_ADD_STR (_TL("Driver"     ), m_pObject->Get_MetaData()["GDAL_DRIVER"].Get_Content().c_str());
121 
122 		if( m_pObject->Get_MetaData()("SURFER_GRID") )
123 			DESC_ADD_STR (_TL("Driver"     ), m_pObject->Get_MetaData()["SURFER_GRID"].Get_Content().c_str());
124 	}
125 	else if( m_pObject->Get_MetaData_DB().Get_Children_Count() )
126 	{
127 		DESC_ADD_STR(_TL("File"            ), m_pObject->Get_File_Name(false));
128 		//const CSG_MetaData	&DB	= m_pObject->Get_MetaData_DB();
129 		//if( DB("DBMS") ) DESC_ADD_STR (_TL("DBMS"    ), DB["DBMS"].Get_Content().c_str());
130 		//if( DB("HOST") ) DESC_ADD_STR (_TL("Host"    ), DB["DBMS"].Get_Content().c_str());
131 		//if( DB("PORT") ) DESC_ADD_STR (_TL("Port"    ), DB["DBMS"].Get_Content().c_str());
132 		//if( DB("NAME") ) DESC_ADD_STR (_TL("Database"), DB["NAME"].Get_Content().c_str());
133 	}
134 	else
135 	{
136 		DESC_ADD_STR (_TL("File"          ), _TL("memory"));
137 	}
138 
139 	DESC_ADD_STR (_TL("Modified"          ), m_pObject->is_Modified() ? _TL("yes") : _TL("no"));
140 	DESC_ADD_STR (_TL("Projection"        ), m_pObject->Get_Projection().Get_Description().c_str());
141 	DESC_ADD_STR (_TL("West"              ), SG_Get_String(Get_Grid()->Get_XMin        (), -CSG_Grid_System::Get_Precision()).c_str());
142 	DESC_ADD_STR (_TL("East"              ), SG_Get_String(Get_Grid()->Get_XMax        (), -CSG_Grid_System::Get_Precision()).c_str());
143 	DESC_ADD_STR (_TL("West-East"         ), SG_Get_String(Get_Grid()->Get_XRange      (), -CSG_Grid_System::Get_Precision()).c_str());
144 	DESC_ADD_STR (_TL("South"             ), SG_Get_String(Get_Grid()->Get_YMin        (), -CSG_Grid_System::Get_Precision()).c_str());
145 	DESC_ADD_STR (_TL("North"             ), SG_Get_String(Get_Grid()->Get_YMax        (), -CSG_Grid_System::Get_Precision()).c_str());
146 	DESC_ADD_STR (_TL("South-North"       ), SG_Get_String(Get_Grid()->Get_YRange      (), -CSG_Grid_System::Get_Precision()).c_str());
147 	DESC_ADD_STR (_TL("Cell Size"         ), SG_Get_String(Get_Grid()->Get_Cellsize    (), -CSG_Grid_System::Get_Precision()).c_str());
148 	DESC_ADD_INT (_TL("Number of Columns" ), Get_Grid()->Get_NX          ());
149 	DESC_ADD_INT (_TL("Number of Rows"    ), Get_Grid()->Get_NY          ());
150 	DESC_ADD_LONG(_TL("Number of Cells"   ), Get_Grid()->Get_NCells      ());
151 	DESC_ADD_LONG(_TL("No Data Cells"     ), Get_Grid()->Get_NoData_Count());
152 	DESC_ADD_STR (_TL("Value Type"        ), SG_Data_Type_Get_Name(Get_Grid()->Get_Type()).c_str());
153 	DESC_ADD_FLT (_TL("Value Minimum"     ), Get_Grid()->Get_Min         ());
154 	DESC_ADD_FLT (_TL("Value Maximum"     ), Get_Grid()->Get_Max         ());
155 	DESC_ADD_FLT (_TL("Value Range"       ), Get_Grid()->Get_Range       ());
156 	DESC_ADD_STR (_TL("No Data Value"     ), Get_Grid()->Get_NoData_Value() < Get_Grid()->Get_NoData_Value(true) ? CSG_String::Format("%f - %f", Get_Grid()->Get_NoData_Value(), Get_Grid()->Get_NoData_Value(true)).c_str() : SG_Get_String(Get_Grid()->Get_NoData_Value(), -2).c_str());
157 	DESC_ADD_FLT (_TL("Arithmetic Mean"   ), Get_Grid()->Get_Mean        ());
158 	DESC_ADD_FLT (_TL("Standard Deviation"), Get_Grid()->Get_StdDev      ());
159 	DESC_ADD_STR (_TL("Memory Size"       ), Get_nBytes_asString(Get_Grid()->Get_Memory_Size(), 2).c_str());
160 
161 	if( Get_Grid()->is_Cached() )
162 	{
163 		DESC_ADD_STR(_TL("File Cache"     ), _TL("activated"));
164 	}
165 
166 	s	+= "</table>";
167 
168 	//-----------------------------------------------------
169 //	s.Append(wxString::Format(wxT("<hr><b>%s</b><font size=\"-1\">"), _TL("Data History")));
170 //	s.Append(Get_Grid()->Get_History().Get_HTML());
171 //	s.Append(wxString::Format(wxT("</font")));
172 
173 	return( s );
174 }
175 
176 //---------------------------------------------------------
Get_Menu(void)177 wxMenu * CWKSP_Grid::Get_Menu(void)
178 {
179 	wxMenu	*pMenu	= new wxMenu(m_pObject->Get_Name());
180 
181 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_WKSP_ITEM_CLOSE);
182 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_GRID_SHOW);
183 
184 	pMenu->AppendSeparator();
185 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVE);
186 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVEAS);
187 
188 	if( PGSQL_has_Connections() )
189 		CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVETODB);
190 
191 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_GRID_SAVEAS_IMAGE);
192 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_GRID_CLIPBOARD_IMAGE);
193 
194 	if( m_pObject->is_File_Native() && m_pObject->is_Modified() )
195 		CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_RELOAD);
196 
197 	if( m_pObject->is_File_Native() )
198 		CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_DEL_FILES);
199 
200 	pMenu->AppendSeparator();
201 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_PROJECTION);
202 
203 	if( m_pObject->Get_MetaData().Get_Children_Count() > 0 )
204 		CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_METADATA);
205 
206 	pMenu->AppendSeparator();
207 	CMD_Menu_Add_Item(pMenu, true , ID_CMD_GRID_HISTOGRAM);
208 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_GRID_SCATTERPLOT);
209 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_FORCE_UPDATE);
210 
211 	pMenu->AppendSeparator();
212 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_GRID_SET_LUT);
213 	CMD_Menu_Add_Item(pMenu, false, ID_CMD_WKSP_ITEM_SETTINGS_COPY);
214 
215 	return( pMenu );
216 }
217 
218 
219 ///////////////////////////////////////////////////////////
220 //														 //
221 ///////////////////////////////////////////////////////////
222 
223 //---------------------------------------------------------
On_Command(int Cmd_ID)224 bool CWKSP_Grid::On_Command(int Cmd_ID)
225 {
226 	switch( Cmd_ID )
227 	{
228 	default:
229 		return( CWKSP_Layer::On_Command(Cmd_ID) );
230 
231 	case ID_CMD_GRID_SAVEAS_IMAGE:
232 		_Save_Image();
233 		break;
234 
235 	case ID_CMD_GRID_CLIPBOARD_IMAGE:
236 		_Save_Image_Clipboard();
237 		break;
238 
239 	case ID_CMD_GRID_HISTOGRAM:
240 		Histogram_Toggle();
241 		break;
242 
243 	case ID_CMD_GRID_SCATTERPLOT:
244 		Add_ScatterPlot();
245 		break;
246 
247 	case ID_CMD_GRID_SET_LUT:
248 		_LUT_Create();
249 		break;
250 
251 	case ID_CMD_GRID_SEL_CLEAR:
252 		_Edit_Clr_Selection();
253 		break;
254 
255 	case ID_CMD_GRID_SEL_DELETE:
256 		_Edit_Del_Selection();
257 		break;
258 	}
259 
260 	return( true );
261 }
262 
263 //---------------------------------------------------------
On_Command_UI(wxUpdateUIEvent & event)264 bool CWKSP_Grid::On_Command_UI(wxUpdateUIEvent &event)
265 {
266 	switch( event.GetId() )
267 	{
268 	default:
269 		return( CWKSP_Layer::On_Command_UI(event) );
270 
271 	case ID_CMD_GRID_SEL_CLEAR:
272 		event.Enable(m_Edit_Attributes.Get_Count() > 0);
273 		break;
274 
275 	case ID_CMD_GRID_SEL_DELETE:
276 		event.Enable(m_Edit_Attributes.Get_Count() > 0);
277 		break;
278 
279 	case ID_CMD_GRID_HISTOGRAM:
280 		event.Check(m_pHistogram != NULL);
281 		break;
282 	}
283 
284 	return( true );
285 }
286 
287 
288 ///////////////////////////////////////////////////////////
289 //														 //
290 ///////////////////////////////////////////////////////////
291 
292 //---------------------------------------------------------
On_Create_Parameters(void)293 void CWKSP_Grid::On_Create_Parameters(void)
294 {
295 	CWKSP_Layer::On_Create_Parameters();
296 
297 	//-----------------------------------------------------
298 	// General...
299 
300 	m_Parameters.Add_String("NODE_GENERAL", "OBJECT_Z_UNIT"  , _TL("Unit"    ), _TL(""), Get_Grid()->Get_Unit   ());
301 	m_Parameters.Add_Double("NODE_GENERAL", "OBJECT_Z_FACTOR", _TL("Z-Scale" ), _TL(""), Get_Grid()->Get_Scaling());
302 	m_Parameters.Add_Double("NODE_GENERAL", "OBJECT_Z_OFFSET", _TL("Z-Offset"), _TL(""), Get_Grid()->Get_Offset ());
303 
304 	//-----------------------------------------------------
305 	// Resampling...
306 
307 	m_Parameters.Add_Choice("NODE_DISPLAY", "DISPLAY_RESAMPLING", _TL("Resampling"),
308 		_TL(""),
309 		CSG_String::Format("%s|%s|%s|%s",
310 			_TL("Nearest Neighbour"),
311 			_TL("Bilinear Interpolation"),
312 			_TL("Bicubic Spline Interpolation"),
313 			_TL("B-Spline Interpolation")
314 		), 0
315 	);
316 
317 	//-----------------------------------------------------
318 	// Transparency...
319 
320 	m_Parameters.Add_Grid("DISPLAY_TRANSPARENCY", "DISPLAY_ALPHA", _TL("Alpha Channel"),
321 		_TL("Alpha channel values are adjusted to the specified range minimum (full transparency) and maximum (full opacity)"),
322 		PARAMETER_INPUT_OPTIONAL, false
323 	)->Get_Parent()->Set_Value((void *)&Get_Grid()->Get_System());
324 
325 	m_Parameters.Add_Range("DISPLAY_ALPHA", "ALPHA_RANGE", _TL("Adjustment"),
326 		_TL(""),
327 		0., 255.
328 	);
329 
330 	//-----------------------------------------------------
331 	// Shading...
332 
333 	m_Parameters.Add_Choice("NODE_DISPLAY", "DISPLAY_SHADING"	, _TL("Shading"),
334 		_TL(""),
335 		CSG_String::Format("%s|%s|%s",
336 			_TL("none"), _TL("normal"), _TL("inverse")
337 		), 0
338 	);
339 
340 	m_Parameters.Add_Double("DISPLAY_SHADING", "SHADING_AZIMUTH", _TL("Azimuth"),
341 		_TL("Direction of the light source, measured in degree clockwise from the North direction."),
342 		315., 0., true, 360., true
343 	);
344 
345 	m_Parameters.Add_Double("DISPLAY_SHADING", "SHADING_HEIGHT"	, _TL("Height"),
346 		_TL("Height of the light source, measured in degree above the horizon."),
347 		45., 0., true, 90., true
348 	);
349 
350 	m_Parameters.Add_Double("DISPLAY_SHADING", "SHADING_EXAGG"	, _TL("Exaggeration"),
351 		_TL(""),
352 		1.
353 	);
354 
355 	m_Parameters.Add_Double("DISPLAY_SHADING", "SHADING_MIN"	, _TL("Minimum"),
356 		_TL(""),
357 		0.
358 	);
359 
360 	m_Parameters.Add_Double("DISPLAY_SHADING", "SHADING_MAX"	, _TL("Maximum"),
361 		_TL(""),
362 		1.5
363 	);
364 
365 	//-----------------------------------------------------
366 	// Classification...
367 
368 	m_Parameters.Add_Node("NODE_COLORS"	, "NODE_SHADE"		, _TL("Shade"),
369 		_TL("")
370 	);
371 
372 	m_Parameters.Add_Choice("NODE_SHADE", "SHADE_MODE"		, _TL("Coloring"),
373 		_TL(""),
374 		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s",
375 			_TL("bright - dark"  ),
376 			_TL("dark - bright"  ),
377 			_TL("white - cyan"   ),
378 			_TL("cyan - white"   ),
379 			_TL("white - magenta"),
380 			_TL("magenta - white"),
381 			_TL("white - yellow" ),
382 			_TL("yellow - white" )
383 		), 0
384 	);
385 
386 	//-----------------------------------------------------
387 	m_Parameters.Add_Bool("NODE_COLORS"	, "RGB_ALPHA"		, _TL("Alpha Channel"),
388 		_TL(""),
389 		false
390 	);
391 
392 	//-----------------------------------------------------
393 	m_Parameters.Add_Node("NODE_COLORS"	, "NODE_OVERLAY"	, _TL("RGB Composite"),
394 		_TL("")
395 	);
396 
397 	m_Parameters.Add_Choice("NODE_OVERLAY", "OVERLAY_MODE"	, _TL("This Color"),
398 		_TL(""),
399 		CSG_String::Format("%s|%s|%s",
400 			_TL("Red"), _TL("Green"), _TL("Blue")
401 		), 0
402 	);
403 
404 	m_Parameters.Add_Grid("NODE_OVERLAY", "OVERLAY_R", _TL("Red"  ), _TL(""), PARAMETER_INPUT_OPTIONAL, false)->Get_Parent()->Set_Value(
405 		(void *)&Get_Grid()->Get_System()
406 	);
407 
408 	m_Parameters.Add_Grid("NODE_OVERLAY", "OVERLAY_G", _TL("Green"), _TL(""), PARAMETER_INPUT_OPTIONAL, false)->Get_Parent()->Set_Value(
409 		(void *)&Get_Grid()->Get_System()
410 	);
411 
412 	m_Parameters.Add_Grid("NODE_OVERLAY", "OVERLAY_B", _TL("Blue" ), _TL(""), PARAMETER_INPUT_OPTIONAL, false)->Get_Parent()->Set_Value(
413 		(void *)&Get_Grid()->Get_System()
414 	);
415 
416 	//-----------------------------------------------------
417 	// Cell Values...
418 
419 	m_Parameters.Add_Bool("NODE_GENERAL", "VALUES_SHOW"		, _TL("Show Cell Values"),
420 		_TL("shows cell values when zoomed"),
421 		false
422 	);
423 
424 	m_Parameters.Add_Font("VALUES_SHOW", "VALUES_FONT"		, _TL("Font"),
425 		_TL("")
426 	);
427 
428 	m_Parameters.Add_Double("VALUES_SHOW", "VALUES_SIZE"	, _TL("Size"),
429 		_TL(""),
430 		15, 0, true , 100., true
431 	);
432 
433 	m_Parameters.Add_Int("VALUES_SHOW", "VALUES_DECIMALS"	, _TL("Decimals"),
434 		_TL(""),
435 		2
436 	);
437 
438 	m_Parameters.Add_Choice("VALUES_SHOW", "VALUES_EFFECT"	, _TL("Boundary Effect"),
439 		_TL(""),
440 		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
441 			_TL("none"        ),
442 			_TL("full frame"  ),
443 			_TL("top"         ),
444 			_TL("top left"    ),
445 			_TL("left"        ),
446 			_TL("bottom left" ),
447 			_TL("bottom"      ),
448 			_TL("bottom right"),
449 			_TL("right"       ),
450 			_TL("top right"   )
451 		), 1
452 	);
453 
454 	m_Parameters.Add_Color("VALUES_EFFECT", "VALUES_EFFECT_COLOR", _TL("Color"),
455 		_TL(""),
456 		SG_GET_RGB(255, 255, 255)
457 	);
458 
459 	//-----------------------------------------------------
460 	// Memory...
461 
462 	m_Parameters.Add_Double("NODE_GENERAL",
463 		"MAX_SAMPLES"	, _TL("Maximum Samples"),
464 		_TL("Maximum number of samples used to build statistics and histograms expressed as percent of the total number of cells."),
465 		100. * (double)Get_Grid()->Get_Max_Samples() / (double)Get_Grid()->Get_NCells(), 0., true, 100., true
466 	);
467 
468 	m_Parameters.Add_Bool("NODE_GENERAL",
469 		"FILE_CACHE"	, _TL("File Cache"),
470 		_TL(""),
471 		Get_Grid()->is_Cached()
472 	);
473 
474 	//-----------------------------------------------------
475 	m_Fit_Colors	= g_pData->Get_Parameter("GRID_STRETCH_DEFAULT")->asInt();
476 }
477 
478 
479 ///////////////////////////////////////////////////////////
480 //														 //
481 ///////////////////////////////////////////////////////////
482 
483 //---------------------------------------------------------
On_DataObject_Changed(void)484 void CWKSP_Grid::On_DataObject_Changed(void)
485 {
486 	//-----------------------------------------------------
487 	m_Parameters.Set_Parameter("OBJECT_Z_UNIT"  , Get_Grid()->Get_Unit   ());
488 	m_Parameters.Set_Parameter("OBJECT_Z_FACTOR", Get_Grid()->Get_Scaling());
489 	m_Parameters.Set_Parameter("OBJECT_Z_OFFSET", Get_Grid()->Get_Offset ());
490 
491 	m_Parameters.Set_Parameter("MAX_SAMPLES"    , 100. * Get_Grid()->Get_Max_Samples() / (double)Get_Grid()->Get_NCells());
492 
493 	m_Parameters.Set_Parameter("FILE_CACHE"     , Get_Grid()->is_Cached  ());
494 
495 	//-----------------------------------------------------
496 	if( m_Parameters("STRETCH_UPDATE")->asBool() == false )	// internal update flag, set by CSG_Tool::DataObject_Update()
497 	{
498 		m_Parameters.Set_Parameter("STRETCH_UPDATE", true);
499 	}
500 	else if( m_Parameters("STRETCH_DEFAULT")->asInt() >= 3 )	// manual
501 	{
502 		m_Parameters.Set_Parameter("STRETCH_DEFAULT", m_Fit_Colors);
503 	}
504 
505 	//-----------------------------------------------------
506 	CWKSP_Layer::On_DataObject_Changed();
507 }
508 
509 //---------------------------------------------------------
On_Parameters_Changed(void)510 void CWKSP_Grid::On_Parameters_Changed(void)
511 {
512 	CWKSP_Layer::On_Parameters_Changed();
513 
514 	//-----------------------------------------------------
515 	Get_Grid()->Set_Unit   (m_Parameters("OBJECT_Z_UNIT"  )->asString());
516 	Get_Grid()->Set_Scaling(m_Parameters("OBJECT_Z_FACTOR")->asDouble(),
517 	                        m_Parameters("OBJECT_Z_OFFSET")->asDouble());
518 
519 	Get_Grid()->Set_Max_Samples(Get_Grid()->Get_NCells() * (m_Parameters("MAX_SAMPLES")->asDouble() / 100.) );
520 
521 	Get_Grid()->Set_Cache(m_Parameters("FILE_CACHE")->asBool());
522 
523 	m_pClassify->Set_Shade_Mode(m_Parameters("SHADE_MODE")->asInt());
524 
525 	//-----------------------------------------------------
526 	if( m_Parameters("STRETCH_DEFAULT")->asInt() < 3 )	// not manual, remember last state...
527 	{
528 		m_Fit_Colors	= m_Parameters("STRETCH_DEFAULT")->asInt();
529 	}
530 }
531 
532 //---------------------------------------------------------
Update(CWKSP_Layer * pChanged)533 bool CWKSP_Grid::Update(CWKSP_Layer *pChanged)
534 {
535 	if( pChanged )
536 	{
537 		if( pChanged == this )
538 		{
539 			return( true );
540 		}
541 
542 		if( pChanged->Get_Type() == WKSP_ITEM_Grid )
543 		{
544 			CSG_Grid	*pGrid	= ((CWKSP_Grid *)pChanged)->Get_Grid();
545 
546 			return(	(m_Parameters("OVERLAY_R")->is_Enabled() && pGrid == m_Parameters("OVERLAY_R")->asGrid())
547 				||  (m_Parameters("OVERLAY_G")->is_Enabled() && pGrid == m_Parameters("OVERLAY_G")->asGrid())
548 				||  (m_Parameters("OVERLAY_B")->is_Enabled() && pGrid == m_Parameters("OVERLAY_B")->asGrid())
549 			);
550 		}
551 
552 		if( pChanged->Get_Type() == WKSP_ITEM_Grids )
553 		{
554 			CSG_Grids	*pGrids	= ((CWKSP_Grids *)pChanged)->Get_Grids();
555 
556 			return(	(m_Parameters("OVERLAY_R")->is_Enabled() && m_Parameters("OVERLAY_R")->asGrid() && pGrids == m_Parameters("OVERLAY_R")->asGrid()->Get_Owner())
557 				||  (m_Parameters("OVERLAY_G")->is_Enabled() && m_Parameters("OVERLAY_G")->asGrid() && pGrids == m_Parameters("OVERLAY_G")->asGrid()->Get_Owner())
558 				||  (m_Parameters("OVERLAY_B")->is_Enabled() && m_Parameters("OVERLAY_B")->asGrid() && pGrids == m_Parameters("OVERLAY_B")->asGrid()->Get_Owner())
559 			);
560 		}
561 	}
562 
563 	return( false );
564 }
565 
566 
567 ///////////////////////////////////////////////////////////
568 //														 //
569 ///////////////////////////////////////////////////////////
570 
571 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter,int Flags)572 int CWKSP_Grid::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter, int Flags)
573 {
574 	//-----------------------------------------------------
575 	if( pParameters->Cmp_Identifier("CLASSIFY") )
576 	{
577 		if( Flags & PARAMETER_CHECK_ENABLE )
578 		{
579 			if( pParameter->Cmp_Identifier("METHOD") )
580 			{
581 				pParameters->Set_Enabled("COUNT"   , pParameter->asInt() != 0);
582 				pParameters->Set_Enabled("COUNTMAX", pParameter->asInt() == 0);
583 			}
584 		}
585 
586 		return( CWKSP_Layer::On_Parameter_Changed(pParameters, pParameter, Flags) );
587 	}
588 
589 	//-----------------------------------------------------
590 	if( Flags & PARAMETER_CHECK_VALUES )
591 	{
592 		if(	pParameter->Cmp_Identifier("OBJECT_Z_FACTOR")
593 		||	pParameter->Cmp_Identifier("OBJECT_Z_OFFSET") )
594 		{
595 			double	newFactor	= (*pParameters)("OBJECT_Z_FACTOR")->asDouble(), oldFactor	= m_Parameters("OBJECT_Z_FACTOR")->asDouble();
596 			double	newOffset	= (*pParameters)("OBJECT_Z_OFFSET")->asDouble(), oldOffset	= m_Parameters("OBJECT_Z_OFFSET")->asDouble();
597 
598 			if( newFactor != 0. && oldFactor != 0. )
599 			{
600 				CSG_Parameter_Range	*newRange	= (*pParameters)("METRIC_ZRANGE")->asRange();
601 				CSG_Parameter_Range	*oldRange	=  m_Parameters ("METRIC_ZRANGE")->asRange();
602 
603 				newRange->Set_Min(((oldRange->Get_Min() - oldOffset) / oldFactor) * newFactor + newOffset);
604 				newRange->Set_Max(((oldRange->Get_Max() - oldOffset) / oldFactor) * newFactor + newOffset);
605 			}
606 		}
607 	}
608 
609 	//-----------------------------------------------------
610 	if( Flags & PARAMETER_CHECK_ENABLE )
611 	{
612 		if(	pParameter->Cmp_Identifier("DISPLAY_SHADING") )
613 		{
614 			pParameters->Set_Enabled("SHADING_AZIMUTH"    , pParameter->asInt() != 0);
615 			pParameters->Set_Enabled("SHADING_HEIGHT"     , pParameter->asInt() != 0);
616 			pParameters->Set_Enabled("SHADING_EXAGG"      , pParameter->asInt() != 0);
617 			pParameters->Set_Enabled("SHADING_MIN"        , pParameter->asInt() != 0);
618 			pParameters->Set_Enabled("SHADING_MAX"        , pParameter->asInt() != 0);
619 		}
620 
621 		if(	pParameter->Cmp_Identifier("COLORS_TYPE") )
622 		{
623 			int		Value	= pParameter->asInt();
624 
625 			pParameters->Set_Enabled("NODE_SINGLE"        , Value == CLASSIFY_SINGLE );
626 			pParameters->Set_Enabled("NODE_LUT"           , Value == CLASSIFY_LUT    );
627 			pParameters->Set_Enabled("NODE_METRIC"        , Value != CLASSIFY_SINGLE && Value != CLASSIFY_LUT);
628 			pParameters->Set_Enabled("NODE_SHADE"         , Value == CLASSIFY_SHADE  );
629 			pParameters->Set_Enabled("NODE_OVERLAY"       , Value == CLASSIFY_OVERLAY);
630 			pParameters->Set_Enabled("RGB_ALPHA"          , Value == CLASSIFY_RGB    );
631 
632 			pParameters->Set_Enabled("DISPLAY_RESAMPLING" , Value != CLASSIFY_LUT    );
633 			pParameters->Set_Enabled("DISPLAY_SHADING"    , Value != CLASSIFY_SHADE  );
634 
635 			pParameters->Set_Enabled("DISPLAY_ALPHA"      , Value != CLASSIFY_RGB    );
636 		}
637 
638 		if( pParameter->Cmp_Identifier("DISPLAY_ALPHA") )
639 		{
640 			pParameters->Set_Enabled("ALPHA_RANGE"        , pParameter->asGrid() != NULL);
641 		}
642 
643 		if(	pParameter->Cmp_Identifier("VALUES_SHOW") )
644 		{
645 			pParameters->Set_Enabled("VALUES_FONT"        , pParameter->asBool());
646 			pParameters->Set_Enabled("VALUES_SIZE"        , pParameter->asBool());
647 			pParameters->Set_Enabled("VALUES_DECIMALS"    , pParameter->asBool());
648 			pParameters->Set_Enabled("VALUES_EFFECT"      , pParameter->asBool());
649 		}
650 
651 		if(	pParameter->Cmp_Identifier("VALUES_EFFECT") )
652 		{
653 			pParameters->Set_Enabled("VALUES_EFFECT_COLOR", pParameter->asInt() > 0);
654 		}
655 
656 		if( pParameter->Cmp_Identifier("OVERLAY_MODE") )
657 		{
658 			(*pParameters)("OVERLAY_R")->Get_Parent()->Set_Enabled(pParameter->asInt() != 0);
659 			(*pParameters)("OVERLAY_G")->Get_Parent()->Set_Enabled(pParameter->asInt() != 1);
660 			(*pParameters)("OVERLAY_B")->Get_Parent()->Set_Enabled(pParameter->asInt() != 2);
661 		}
662 	}
663 
664 	return( CWKSP_Layer::On_Parameter_Changed(pParameters, pParameter, Flags) );
665 }
666 
667 
668 ///////////////////////////////////////////////////////////
669 //														 //
670 ///////////////////////////////////////////////////////////
671 
672 //---------------------------------------------------------
_LUT_Create(void)673 void CWKSP_Grid::_LUT_Create(void)
674 {
675 	//-----------------------------------------------------
676 	static CSG_Parameters	PStatic;
677 
678 	if( PStatic.Get_Count() == 0 )
679 	{
680 		PStatic.Create(_TL("Classify"));
681 		PStatic.Add_Colors("", "COLORS"  , _TL("Colors"                   ), _TL(""));
682 		PStatic.Add_Int   ("", "COUNT"   , _TL("Number of Classes"        ), _TL(""),   10, 1, true);
683 		PStatic.Add_Int   ("", "COUNTMAX", _TL("Maximum Number of Classes"), _TL(""), 1000, 1, true);
684 		PStatic.Add_Choice("", "METHOD"  , _TL("Classification"           ), _TL(""),
685 			CSG_String::Format("%s|%s|%s|%s",
686 				_TL("unique values"),
687 				_TL("equal intervals"),
688 				_TL("quantiles"),
689 				_TL("natural breaks")
690 			), 1
691 		);
692 	}
693 
694 	CSG_Parameters	Parameters(_TL("Classify"), _TL(""), SG_T("CLASSIFY"));
695 
696 	Parameters.Assign_Parameters(&PStatic);
697 
698 	Parameters("COLORS")->asColors()->Assign(Get_Colors());
699 
700 	Parameters.Set_Callback_On_Parameter_Changed(&Parameter_Callback);
701 
702 	if( !DLG_Parameters(&Parameters) )
703 	{
704 		return;
705 	}
706 
707 	PStatic.Assign_Values(&Parameters);
708 
709 	//-----------------------------------------------------
710 	CSG_Colors	Colors(*Parameters("COLORS")->asColors());
711 
712 	if( Parameters("METHOD")->asInt() != 0 )
713 	{
714 		Colors.Set_Count(Parameters("COUNT")->asInt());
715 	}
716 
717 	CSG_Table	Classes(m_Parameters("LUT")->asTable());
718 
719 	switch( Parameters("METHOD")->asInt() )
720 	{
721 	//-----------------------------------------------------
722 	case 0:	// unique values
723 	{
724 		CSG_Unique_Number_Statistics	s;
725 
726 		int	maxClasses	= Parameters("COUNTMAX")->asInt();
727 
728 		for(sLong iCell = 0; iCell<Get_Grid()->Get_NCells() && s.Get_Count()<maxClasses && PROGRESSBAR_Set_Position(iCell, Get_Grid()->Get_NCells()); iCell++)
729 		{
730 			if( !Get_Grid()->is_NoData(iCell) )
731 			{
732 				s	+= Get_Grid()->asDouble(iCell);
733 			}
734 		}
735 
736 		Colors.Set_Count(s.Get_Count());
737 
738 		for(int iClass=0; iClass<s.Get_Count(); iClass++)
739 		{
740 			double		Value	= s.Get_Value(iClass);
741 
742 			CSG_String	Name	= SG_Get_String(Value, -2);
743 
744 			CSG_Table_Record	*pClass	= Classes.Add_Record();
745 
746 			pClass->Set_Value(0, Colors[iClass]);	// Color
747 			pClass->Set_Value(1, Name          );	// Name
748 			pClass->Set_Value(2, Name          );	// Description
749 			pClass->Set_Value(3, Value         );	// Minimum
750 			pClass->Set_Value(4, Value         );	// Maximum
751 		}
752 
753 		break;
754 	}
755 
756 	//-----------------------------------------------------
757 	case 1:	// equal intervals
758 		if( Get_Grid()->Get_Range() && Colors.Get_Count() > 0 )
759 		{
760 			double	Minimum, Maximum, Interval;
761 
762 			Interval	= Get_Grid()->Get_Range() / (double)Colors.Get_Count();
763 			Minimum		= Get_Grid()->Get_Min  ();
764 
765 			for(int iClass=0; iClass<Colors.Get_Count(); iClass++, Minimum+=Interval)
766 			{
767 				Maximum	= iClass < Colors.Get_Count() - 1 ? Minimum + Interval : Get_Grid()->Get_Max() + 1.;
768 
769 				CSG_String	Name	= SG_Get_String(Minimum, -2)
770 							+ " - " + SG_Get_String(Maximum, -2);
771 
772 				CSG_Table_Record	*pClass	= Classes.Add_Record();
773 
774 				pClass->Set_Value(0, Colors[iClass]);	// Color
775 				pClass->Set_Value(1, Name          );	// Name
776 				pClass->Set_Value(2, Name          );	// Description
777 				pClass->Set_Value(3, Minimum       );	// Minimum
778 				pClass->Set_Value(4, Maximum       );	// Maximum
779 			}
780 		}
781 		break;
782 
783 	//-----------------------------------------------------
784 	case 2:	// quantiles
785 		{
786 			if( Get_Grid()->Get_NCells() < Colors.Get_Count() )
787 			{
788 				Colors.Set_Count(Get_Grid()->Get_NCells());
789 			}
790 
791 			double	Minimum, Maximum	= Get_Grid()->Get_Histogram().Get_Quantile(0.);
792 
793 			double	Step	= 1. / Colors.Get_Count();
794 
795 			for(int iClass=0; iClass<Colors.Get_Count(); iClass++)
796 			{
797 				Minimum	= Maximum;
798 				Maximum	= Get_Grid()->Get_Histogram().Get_Quantile((1. + iClass) / Colors.Get_Count());
799 
800 				CSG_String	Name	= SG_Get_String(Minimum, -2)
801 							+ " - " + SG_Get_String(Maximum, -2);
802 
803 				CSG_Table_Record	*pClass	= Classes.Add_Record();
804 
805 				pClass->Set_Value(0, Colors[iClass]);	// Color
806 				pClass->Set_Value(1, Name          );	// Name
807 				pClass->Set_Value(2, Name          );	// Description
808 				pClass->Set_Value(3, Minimum       );	// Minimum
809 				pClass->Set_Value(4, Maximum       );	// Maximum
810 			}
811 		}
812 		break;
813 
814 	//-----------------------------------------------------
815 	case 3:	// natural breaks
816 		{
817 			CSG_Natural_Breaks	Breaks(Get_Grid(), Colors.Get_Count(), 255);
818 
819 			if( Breaks.Get_Count() <= Colors.Get_Count() ) return;
820 
821 			for(int iClass=0; iClass<Colors.Get_Count(); iClass++)
822 			{
823 				CSG_Table_Record	*pClass	= Classes.Add_Record();
824 
825 				double	Minimum	= Breaks[iClass    ];
826 				double	Maximum	= Breaks[iClass + 1];
827 
828 				CSG_String	Name	= SG_Get_String(Minimum, -2)
829 							+ " - " + SG_Get_String(Maximum, -2);
830 
831 				pClass->Set_Value(0, Colors[iClass]);	// Color
832 				pClass->Set_Value(1, Name          );	// Name
833 				pClass->Set_Value(2, Name          );	// Description
834 				pClass->Set_Value(3, Minimum       );	// Minimum
835 				pClass->Set_Value(4, Maximum       );	// Maximum
836 			}
837 		}
838 		break;
839 	}
840 
841 	//-----------------------------------------------------
842 	PROGRESSBAR_Set_Position(0);
843 
844 	if( Classes.Get_Count() > 0 )
845 	{
846 		m_Parameters("LUT")->asTable()->Assign_Values(&Classes);
847 
848 		m_Parameters("COLORS_TYPE")->Set_Value(CLASSIFY_LUT);	// Lookup Table
849 
850 		Parameters_Changed();
851 	}
852 }
853 
854 
855 ///////////////////////////////////////////////////////////
856 //														 //
857 ///////////////////////////////////////////////////////////
858 
859 //---------------------------------------------------------
Get_Value(CSG_Point ptWorld,double Epsilon)860 wxString CWKSP_Grid::Get_Value(CSG_Point ptWorld, double Epsilon)
861 {
862 	wxString	s;	double	Value;
863 
864 	if( Get_Grid()->Get_Value(ptWorld, Value, GRID_RESAMPLING_NearestNeighbour) )
865 	{
866 		switch( m_pClassify->Get_Mode() )
867 		{
868 		default:
869 			s	= SG_Get_String(Value, -12).c_str();
870 
871 			if( !Get_Grid()->Get_Unit().is_Empty() )
872 			{
873 				s += " "; s += Get_Grid()->Get_Unit().c_str();
874 			}
875 			break;
876 
877 		case CLASSIFY_RGB:
878 			s.Printf("R%03d G%03d B%03d", SG_GET_R((int)Value), SG_GET_G((int)Value), SG_GET_B((int)Value));
879 			break;
880 
881 		case CLASSIFY_LUT:
882 			s	= m_pClassify->Get_Class_Name_byValue(Value);
883 			break;
884 		}
885 	}
886 
887 	return( s );
888 }
889 
890 
891 ///////////////////////////////////////////////////////////
892 //														 //
893 ///////////////////////////////////////////////////////////
894 
895 //---------------------------------------------------------
Get_Value_Minimum(void)896 double CWKSP_Grid::Get_Value_Minimum(void)	{	return( ((CSG_Grid *)m_pObject)->Get_Min   () );	}
Get_Value_Maximum(void)897 double CWKSP_Grid::Get_Value_Maximum(void)	{	return( ((CSG_Grid *)m_pObject)->Get_Max   () );	}
Get_Value_Range(void)898 double CWKSP_Grid::Get_Value_Range  (void)	{	return( ((CSG_Grid *)m_pObject)->Get_Range () );	}
Get_Value_Mean(void)899 double CWKSP_Grid::Get_Value_Mean   (void)	{	return( ((CSG_Grid *)m_pObject)->Get_Mean  () );	}
Get_Value_StdDev(void)900 double CWKSP_Grid::Get_Value_StdDev (void)	{	return( ((CSG_Grid *)m_pObject)->Get_StdDev() );	}
901 
902 
903 ///////////////////////////////////////////////////////////
904 //														 //
905 ///////////////////////////////////////////////////////////
906 
907 //---------------------------------------------------------
Edit_Get_Menu(void)908 wxMenu * CWKSP_Grid::Edit_Get_Menu(void)
909 {
910 	if( m_Edit_Attributes.Get_Count() < 1 )
911 	{
912 		return( NULL );
913 	}
914 
915 	wxMenu	*pMenu	= new wxMenu;
916 
917 	CMD_Menu_Add_Item(pMenu, true , ID_CMD_GRID_SEL_CLEAR);
918 	CMD_Menu_Add_Item(pMenu, true , ID_CMD_GRID_SEL_DELETE);
919 
920 	return( pMenu );
921 }
922 
923 //---------------------------------------------------------
Edit_Get_Extent(void)924 TSG_Rect CWKSP_Grid::Edit_Get_Extent(void)
925 {
926 	if( m_Edit_Attributes.Get_Count() > 0 )
927 	{
928 		return( CSG_Rect(
929 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_xGrid_to_World(m_xSel),
930 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_yGrid_to_World(m_ySel),
931 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_xGrid_to_World(m_xSel + m_Edit_Attributes.Get_Field_Count() - 1),
932 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_yGrid_to_World(m_ySel + m_Edit_Attributes.Get_Count()))
933 		);
934 	}
935 
936 	return( Get_Grid()->Get_Extent().m_rect );
937 }
938 
939 //---------------------------------------------------------
Edit_On_Key_Down(int KeyCode)940 bool CWKSP_Grid::Edit_On_Key_Down(int KeyCode)
941 {
942 	switch( KeyCode )
943 	{
944 	default:
945 		return( false );
946 
947 	case WXK_DELETE:
948 		return( _Edit_Del_Selection() );
949 	}
950 }
951 
952 //---------------------------------------------------------
Edit_On_Mouse_Up(CSG_Point Point,double ClientToWorld,int Key)953 bool CWKSP_Grid::Edit_On_Mouse_Up(CSG_Point Point, double ClientToWorld, int Key)
954 {
955 	if( Key & TOOL_INTERACTIVE_KEY_LEFT )
956 	{
957 		g_pActive->Update_Attributes();
958 
959 		m_Edit_Attributes.Destroy();
960 		m_Edit_Attributes.Add_Field("ROW", SG_DATATYPE_Int);
961 
962 		CSG_Rect	rWorld(m_Edit_Mouse_Down, Point);
963 
964 		if( rWorld.Intersects(Get_Grid()->Get_Extent(true)) )
965 		{
966 			m_xSel	= Get_Grid()->Get_System().Get_xWorld_to_Grid(rWorld.Get_XMin()); if( m_xSel < 0 ) m_xSel = 0;
967 			int	nx	= Get_Grid()->Get_System().Get_xWorld_to_Grid(rWorld.Get_XMax()); if( nx >= Get_Grid()->Get_NX() ) nx = Get_Grid()->Get_NX() - 1;
968 			nx	= 1 + nx - m_xSel;
969 
970 			m_ySel	= Get_Grid()->Get_System().Get_yWorld_to_Grid(rWorld.Get_YMin()); if( m_ySel < 0 ) m_ySel = 0;
971 			int	ny	= Get_Grid()->Get_System().Get_yWorld_to_Grid(rWorld.Get_YMax()); if( ny >= Get_Grid()->Get_NY() ) ny = Get_Grid()->Get_NY() - 1;
972 			ny	= 1 + ny - m_ySel;
973 
974 			if( nx > 0 && ny > 0 )
975 			{
976 				int	Maximum = g_pData->Get_Parameter("GRID_SELECT_MAX")->asInt();
977 
978 				if( nx > Maximum )
979 				{
980 					m_xSel	+= (nx - Maximum) / 2;
981 					nx		= Maximum;
982 				}
983 
984 				if( ny > Maximum )
985 				{
986 					m_ySel	+= (ny - Maximum) / 2;
987 					ny		= Maximum;
988 				}
989 
990 				for(int x=0; x<nx; x++)
991 				{
992 					m_Edit_Attributes.Add_Field(CSG_String::Format("%d", m_xSel + 1 + x), Get_Grid()->Get_Type());
993 				}
994 
995 				for(int y=0; y<ny; y++)
996 				{
997 					CSG_Table_Record	*pRecord	= m_Edit_Attributes.Add_Record();
998 
999 					for(int x=0; x<nx; x++)
1000 					{
1001 						pRecord->Set_Value(0, m_ySel + ny - y);
1002 
1003 						if( !Get_Grid()->is_NoData(m_xSel + x, m_ySel + ny - 1 - y) )
1004 						{
1005 							pRecord->Set_Value(1 + x, Get_Grid()->asDouble(m_xSel + x, m_ySel + ny - 1 - y));
1006 						}
1007 						else
1008 						{
1009 							pRecord->Set_NoData(1 + x);
1010 						}
1011 					}
1012 				}
1013 			}
1014 		}
1015 
1016 		g_pActive->Update_Attributes();
1017 
1018 		Update_Views();
1019 
1020 		return( true );
1021 	}
1022 
1023 	return( false );
1024 }
1025 
1026 //---------------------------------------------------------
Edit_Set_Attributes(void)1027 bool CWKSP_Grid::Edit_Set_Attributes(void)
1028 {
1029 	if( m_Edit_Attributes.Get_Count() > 0 )
1030 	{
1031 		for(int y=0; y<m_Edit_Attributes.Get_Count(); y++)
1032 		{
1033 			CSG_Table_Record	*pRecord	= m_Edit_Attributes.Get_Record(m_Edit_Attributes.Get_Count() - 1 - y);
1034 
1035 			for(int x=0, xx=1; xx<m_Edit_Attributes.Get_Field_Count(); x++, xx++)
1036 			{
1037 				if( !pRecord->is_NoData(xx) )
1038 				{
1039 					Get_Grid()->Set_Value(m_xSel + x, m_ySel + y, pRecord->asDouble(xx));
1040 				}
1041 				else
1042 				{
1043 					Get_Grid()->Set_NoData(m_xSel + x, m_ySel + y);
1044 				}
1045 			}
1046 		}
1047 
1048 		Update_Views();
1049 
1050 		return( true );
1051 	}
1052 
1053 	return( false );
1054 }
1055 
1056 
1057 ///////////////////////////////////////////////////////////
1058 //														 //
1059 ///////////////////////////////////////////////////////////
1060 
1061 //---------------------------------------------------------
_Edit_Clr_Selection(void)1062 bool CWKSP_Grid::_Edit_Clr_Selection(void)
1063 {
1064 	if( m_Edit_Attributes.Get_Count() > 0 )
1065 	{
1066 		m_Edit_Attributes.Destroy();
1067 
1068 		g_pActive->Update_Attributes();
1069 
1070 		Update_Views();
1071 
1072 		return( true );
1073 	}
1074 
1075 	return( false );
1076 }
1077 
1078 //---------------------------------------------------------
_Edit_Del_Selection(void)1079 bool CWKSP_Grid::_Edit_Del_Selection(void)
1080 {
1081 	if( m_Edit_Attributes.Get_Count() > 0 && DLG_Message_Confirm(_TL("Set selected values to no data."), _TL("Delete")) )
1082 	{
1083 		for(int y=0; y<m_Edit_Attributes.Get_Count(); y++)
1084 		{
1085 			for(int x=0, xx=1; xx<m_Edit_Attributes.Get_Field_Count(); x++, xx++)
1086 			{
1087 				m_Edit_Attributes[y].Set_NoData(xx);
1088 
1089 				Get_Grid()->Set_NoData(m_xSel + x, m_ySel + y);
1090 			}
1091 		}
1092 
1093 		g_pActive->Update_Attributes();
1094 
1095 		Update_Views();
1096 
1097 		return( true );
1098 	}
1099 
1100 	return( false );
1101 }
1102 
1103 
1104 ///////////////////////////////////////////////////////////
1105 //														 //
1106 ///////////////////////////////////////////////////////////
1107 
1108 //---------------------------------------------------------
Fit_Colors(const CSG_Rect & rWorld)1109 bool CWKSP_Grid::Fit_Colors(const CSG_Rect &rWorld)
1110 {
1111 	double	Minimum, Maximum;
1112 
1113 	switch( m_Fit_Colors )
1114 	{
1115 	default: {	CSG_Simple_Statistics s; if( !Get_Grid()->Get_Statistics(rWorld, s) ) { return( false ); }
1116 		Minimum	= s.Get_Minimum() + s.Get_Range() * m_Parameters("STRETCH_LINEAR.MIN")->asDouble() / 100.;
1117 		Maximum	= s.Get_Minimum() + s.Get_Range() * m_Parameters("STRETCH_LINEAR.MAX")->asDouble() / 100.;
1118 		break;	}
1119 
1120 	case  1: {	CSG_Simple_Statistics s; if( !Get_Grid()->Get_Statistics(rWorld, s) ) { return( false ); }
1121 		double	d	= m_Parameters("STRETCH_STDDEV")->asDouble() * s.Get_StdDev();
1122 		Minimum	= s.Get_Mean() - d; if( m_Parameters("STRETCH_INRANGE")->asBool() && Minimum < Get_Grid()->Get_Min() ) Minimum = Get_Grid()->Get_Min();
1123 		Maximum	= s.Get_Mean() + d; if( m_Parameters("STRETCH_INRANGE")->asBool() && Maximum > Get_Grid()->Get_Max() ) Maximum = Get_Grid()->Get_Max();
1124 		break;	}
1125 
1126 	case  2: {	CSG_Histogram         h; if( !Get_Grid()->Get_Histogram (rWorld, h) ) { return( false ); }
1127 		Minimum	= h.Get_Quantile(m_Parameters("STRETCH_PCTL.MIN")->asDouble() / 100.);
1128 		Maximum	= h.Get_Quantile(m_Parameters("STRETCH_PCTL.MAX")->asDouble() / 100.);
1129 		break;	}
1130 	}
1131 
1132 	return( Set_Color_Range(Minimum, Maximum) );
1133 }
1134 
1135 
1136 ///////////////////////////////////////////////////////////
1137 //														 //
1138 ///////////////////////////////////////////////////////////
1139 
1140 //---------------------------------------------------------
asImage(CSG_Grid * pImage)1141 bool CWKSP_Grid::asImage(CSG_Grid *pImage)
1142 {
1143 	wxBitmap	BMP;
1144 
1145 	if( pImage && Get_Image_Grid(BMP) )
1146 	{
1147 		wxImage	IMG(BMP.ConvertToImage());
1148 
1149 		pImage->Create(Get_Grid(), SG_DATATYPE_Int);
1150 
1151 		#pragma omp parallel for
1152 		for(int y=0; y<pImage->Get_NY(); y++)
1153 		{
1154 			for(int x=0; x<pImage->Get_NX(); x++)
1155 			{
1156 				pImage->Set_Value(x, y, SG_GET_RGB(IMG.GetRed(x, y), IMG.GetGreen(x, y), IMG.GetBlue(x, y)));
1157 			}
1158 		}
1159 
1160 		return( true );
1161 	}
1162 
1163 	return( false );
1164 }
1165 
1166 //---------------------------------------------------------
_Save_Image(void)1167 bool CWKSP_Grid::_Save_Image(void)
1168 {
1169 	static CSG_Parameters	P(NULL, _TL("Save Grid as Image..."), _TL(""), SG_T(""));
1170 
1171 	if( P.Get_Count() == 0 )
1172 	{
1173 		P.Add_Bool  ("", "WORLD", _TL("Save Georeference"), _TL(""), true);
1174 		P.Add_Bool  ("", "LG"   , _TL("Legend: Save"     ), _TL(""), true);
1175 		P.Add_Double("", "LZ"   , _TL("Legend: Zoom"     ), _TL(""), 1., 0., true);
1176 	}
1177 
1178 	//-----------------------------------------------------
1179 	int			Type;
1180 	wxString	File;
1181 	wxBitmap	Bitmap;
1182 
1183 	if( !DLG_Image_Save(File, Type) || !DLG_Parameters(&P) || !Get_Image_Grid(Bitmap) )
1184 	{
1185 		return( false );
1186 	}
1187 
1188 	Bitmap.SaveFile(File, (wxBitmapType)Type);
1189 
1190 	//-----------------------------------------------------
1191 	if( P("LG")->asBool() && Get_Image_Legend(Bitmap, P("LZ")->asDouble()) )
1192 	{
1193 		wxFileName	fn(File); fn.SetName(wxString::Format("%s_legend", fn.GetName().c_str()));
1194 
1195 		Bitmap.SaveFile(fn.GetFullPath(), (wxBitmapType)Type);
1196 	}
1197 
1198 	if( P("WORLD")->asBool() )
1199 	{
1200 		wxFileName	fn(File);
1201 
1202 		switch( Type )
1203 		{
1204 		default                : fn.SetExt("world");	break;
1205 		case wxBITMAP_TYPE_BMP : fn.SetExt("bpw"  );	break;
1206 		case wxBITMAP_TYPE_GIF : fn.SetExt("gfw"  );	break;
1207 		case wxBITMAP_TYPE_JPEG: fn.SetExt("jgw"  );	break;
1208 		case wxBITMAP_TYPE_PNG : fn.SetExt("pgw"  );	break;
1209 		case wxBITMAP_TYPE_PCX : fn.SetExt("pxw"  );	break;
1210 		case wxBITMAP_TYPE_TIF : fn.SetExt("tfw"  );	break;
1211 		}
1212 
1213 		CSG_File	Stream;
1214 
1215 		if( Stream.Open(fn.GetFullPath().wx_str(), SG_FILE_W, false) )
1216 		{
1217 			Stream.Printf("%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n%.10f\n",
1218 				 Get_Grid()->Get_Cellsize(), 0., 0.,
1219 				-Get_Grid()->Get_Cellsize(),
1220 				 Get_Grid()->Get_XMin(),
1221 				 Get_Grid()->Get_YMax()
1222 			);
1223 		}
1224 	}
1225 
1226 	return( true );
1227 }
1228 
1229 //---------------------------------------------------------
_Save_Image_Clipboard(void)1230 bool CWKSP_Grid::_Save_Image_Clipboard(void)
1231 {
1232 	wxBitmap	Bitmap;
1233 
1234 	if( Get_Image_Grid(Bitmap) && wxTheClipboard->Open() )
1235 	{
1236 		wxBitmapDataObject	*pBitmap	= new wxBitmapDataObject;
1237 		pBitmap->SetBitmap(Bitmap);
1238 		wxTheClipboard->SetData(pBitmap);
1239 		wxTheClipboard->Close();
1240 
1241 		return( true );
1242 	}
1243 
1244 	return( false );
1245 }
1246 
1247 //---------------------------------------------------------
Get_Image_Grid(wxBitmap & BMP,bool bFitSize)1248 bool CWKSP_Grid::Get_Image_Grid(wxBitmap &BMP, bool bFitSize)
1249 {
1250 	if( bFitSize || (BMP.GetWidth() > 0 && BMP.GetHeight() > 0) )
1251 	{
1252 		Set_Buisy_Cursor(true);
1253 
1254 		if( bFitSize )
1255 		{
1256 			BMP.Create(Get_Grid()->Get_NX(), Get_Grid()->Get_NY());
1257 		}
1258 
1259 		wxMemoryDC		dc;
1260 		wxRect			r(0, 0, BMP.GetWidth(), BMP.GetHeight());
1261 		CWKSP_Map_DC	dc_Map(Get_Extent(), r, 1., SG_GET_RGB(255, 255, 255));
1262 
1263 		On_Draw(dc_Map, false);
1264 
1265 		dc.SelectObject(BMP);
1266 		dc.SetBackground(*wxWHITE_BRUSH);
1267 		dc.Clear();
1268 
1269 		dc_Map.Draw(dc);
1270 
1271 		dc.SelectObject(wxNullBitmap);
1272 
1273 		Set_Buisy_Cursor(false);
1274 
1275 		return( true );
1276 	}
1277 
1278 	return( false );
1279 }
1280 
1281 //---------------------------------------------------------
Get_Image_Legend(wxBitmap & BMP,double Zoom)1282 bool CWKSP_Grid::Get_Image_Legend(wxBitmap &BMP, double Zoom)
1283 {
1284 	if( Zoom > 0. )
1285 	{
1286 		wxMemoryDC	dc;
1287 		wxSize		s(Get_Legend()->Get_Size(Zoom, 1.));
1288 
1289 		BMP.Create(s.GetWidth(), s.GetHeight());
1290 
1291 		dc.SelectObject(BMP);
1292 		dc.SetBackground(*wxWHITE_BRUSH);
1293 		dc.Clear();
1294 
1295 		Get_Legend()->Draw(dc, Zoom, 1., wxPoint(0, 0));
1296 
1297 		dc.SelectObject(wxNullBitmap);
1298 
1299 		return( true );
1300 	}
1301 
1302 	return( false );
1303 }
1304 
1305 
1306 ///////////////////////////////////////////////////////////
1307 //														 //
1308 ///////////////////////////////////////////////////////////
1309 
1310 //---------------------------------------------------------
On_Draw(CWKSP_Map_DC & dc_Map,int Flags)1311 void CWKSP_Grid::On_Draw(CWKSP_Map_DC &dc_Map, int Flags)
1312 {
1313 	if(	Get_Extent().Intersects(dc_Map.m_rWorld) == INTERSECTION_None )
1314 	{
1315 		return;
1316 	}
1317 
1318 	//-----------------------------------------------------
1319 	int	Mode	= m_pClassify->Get_Mode() == CLASSIFY_SHADE                                          ? IMG_MODE_SHADING
1320 				: m_pClassify->Get_Mode() == CLASSIFY_RGB && m_Parameters("RGB_ALPHA"    )->asBool() ? IMG_MODE_TRANSPARENT_ALPHA
1321 				: m_pClassify->Get_Mode() != CLASSIFY_RGB && m_Parameters("DISPLAY_ALPHA")->asGrid() ? IMG_MODE_TRANSPARENT_ALPHA
1322 				: IMG_MODE_TRANSPARENT;
1323 
1324 	if( !dc_Map.IMG_Draw_Begin(m_Parameters("DISPLAY_TRANSPARENCY")->asDouble() / 100., Mode) )
1325 	{
1326 		return;
1327 	}
1328 
1329 	//-----------------------------------------------------
1330 	m_pAlpha   = m_Parameters("DISPLAY_ALPHA"  )->asGrid  ();
1331 	m_Alpha[0] = m_Parameters("ALPHA_RANGE.MIN")->asDouble();
1332 	m_Alpha[1] = m_Parameters("ALPHA_RANGE.MAX")->asDouble() - m_Alpha[0]; m_Alpha[1] = m_Alpha[1] ? 255. / m_Alpha[1] : 1.;
1333 
1334 	//-----------------------------------------------------
1335 	TSG_Grid_Resampling	Resampling;
1336 
1337 	if( m_pClassify->Get_Mode() == CLASSIFY_LUT )
1338 	{
1339 		Resampling	= GRID_RESAMPLING_NearestNeighbour;
1340 	}
1341 	else switch( m_Parameters("DISPLAY_RESAMPLING")->asInt() )
1342 	{
1343 	default: Resampling = GRID_RESAMPLING_NearestNeighbour; break;
1344 	case  1: Resampling = GRID_RESAMPLING_Bilinear        ; break;
1345 	case  2: Resampling = GRID_RESAMPLING_BicubicSpline   ; break;
1346 	case  3: Resampling = GRID_RESAMPLING_BSpline         ; break;
1347 	}
1348 
1349 	//-----------------------------------------------------
1350 	m_Shade_Mode	= m_Parameters("COLORS_TYPE"    )->asInt() != CLASSIFY_SHADE
1351 					? m_Parameters("DISPLAY_SHADING")->asInt() : 0;
1352 
1353 	if( m_Shade_Mode && Get_Grid()->Get_Range() > 0. )
1354 	{
1355 	//	m_Shade_Parms[0]	= m_Parameters("SHADING_EXAGG")->asDouble() * Get_Grid()->Get_Cellsize() / Get_Grid()->Get_StdDev();
1356 		m_Shade_Parms[0]	= m_Parameters("SHADING_EXAGG")->asDouble() * Get_Grid()->Get_Cellsize() / 25.;
1357 		m_Shade_Parms[1]	= sin(M_DEG_TO_RAD * m_Parameters("SHADING_HEIGHT")->asDouble());
1358 		m_Shade_Parms[2]	= cos(M_DEG_TO_RAD * m_Parameters("SHADING_HEIGHT")->asDouble());
1359 		m_Shade_Parms[3]	=     M_DEG_TO_RAD * m_Parameters("SHADING_AZIMUTH")->asDouble();
1360 		m_Shade_Parms[4]	= m_Parameters("SHADING_MIN")->asDouble();
1361 		m_Shade_Parms[5]	= m_Parameters("SHADING_MAX")->asDouble() - m_Shade_Parms[4];
1362 	}
1363 
1364 	//-----------------------------------------------------
1365 	m_pClassify->Set_Shade_Mode(m_Parameters("SHADE_MODE")->asInt());
1366 
1367 	if(	dc_Map.m_DC2World >= Get_Grid()->Get_Cellsize()
1368 	||	Resampling != GRID_RESAMPLING_NearestNeighbour
1369 	||  m_Parameters("COLORS_TYPE")->asInt() == CLASSIFY_OVERLAY )
1370 	{
1371 		_Draw_Grid_Nodes(dc_Map, Resampling);
1372 	}
1373 	else
1374 	{
1375 		_Draw_Grid_Cells(dc_Map);
1376 	}
1377 
1378 	//-----------------------------------------------------
1379 	dc_Map.IMG_Draw_End();
1380 
1381 	if( (Flags & LAYER_DRAW_FLAG_NOLABELS) == 0 )
1382 	{
1383 		_Draw_Values(dc_Map);
1384 	}
1385 
1386 	if( (Flags & LAYER_DRAW_FLAG_NOEDITS) == 0 )
1387 	{
1388 		_Draw_Edit(dc_Map);
1389 	}
1390 }
1391 
1392 //---------------------------------------------------------
_Draw_Grid_Nodes(CWKSP_Map_DC & dc_Map,TSG_Grid_Resampling Resampling)1393 void CWKSP_Grid::_Draw_Grid_Nodes(CWKSP_Map_DC &dc_Map, TSG_Grid_Resampling Resampling)
1394 {
1395 	CSG_Grid *pOverlay[2]; CSG_Scaler	Scaler[2];
1396 
1397 	_Get_Overlay(pOverlay, Scaler);
1398 
1399 	CSG_Rect	rMap(dc_Map.m_rWorld);	rMap.Intersect(Get_Grid()->Get_Extent(true));
1400 
1401 	int	axDC	= (int)dc_Map.xWorld2DC(rMap.Get_XMin());	if( axDC < 0 )	axDC	= 0;
1402 	int	bxDC	= (int)dc_Map.xWorld2DC(rMap.Get_XMax());	if( bxDC >= dc_Map.m_rDC.GetWidth () )	bxDC	= dc_Map.m_rDC.GetWidth () - 1;
1403 	int	ayDC	= (int)dc_Map.yWorld2DC(rMap.Get_YMin());	if( ayDC >= dc_Map.m_rDC.GetHeight() )	ayDC	= dc_Map.m_rDC.GetHeight() - 1;
1404 	int	byDC	= (int)dc_Map.yWorld2DC(rMap.Get_YMax());	if( byDC < 0 )	byDC	= 0;
1405 	int	nyDC	= abs(ayDC - byDC);
1406 
1407 	if( Get_Grid()->is_Cached() )
1408 	{
1409 		for(int iyDC=0; iyDC<=nyDC; iyDC++)
1410 		{
1411 			_Draw_Grid_Nodes(dc_Map, Resampling, ayDC - iyDC, axDC, bxDC, pOverlay, Scaler);
1412 		}
1413 	}
1414 	else
1415 	{
1416 		#pragma omp parallel for
1417 		for(int iyDC=0; iyDC<=nyDC; iyDC++)
1418 		{
1419 			_Draw_Grid_Nodes(dc_Map, Resampling, ayDC - iyDC, axDC, bxDC, pOverlay, Scaler);
1420 		}
1421 	}
1422 }
1423 
1424 //---------------------------------------------------------
_Get_Overlay(CSG_Grid * pOverlay[2],CSG_Scaler Scaler[2])1425 void CWKSP_Grid::_Get_Overlay(CSG_Grid *pOverlay[2], CSG_Scaler Scaler[2])
1426 {
1427 	if( m_pClassify->Get_Mode() != CLASSIFY_OVERLAY )
1428 	{
1429 		pOverlay [0] = pOverlay [1] = NULL;
1430 	}
1431 	else
1432 	{
1433 		switch( m_Parameters("OVERLAY_MODE")->asInt() )
1434 		{
1435 		default:	// this = red
1436 			pOverlay[0]	= m_Parameters("OVERLAY_G")->asGrid();
1437 			pOverlay[1]	= m_Parameters("OVERLAY_B")->asGrid();
1438 			break;
1439 
1440 		case  1:	// this = green
1441 			pOverlay[0]	= m_Parameters("OVERLAY_R")->asGrid();
1442 			pOverlay[1]	= m_Parameters("OVERLAY_B")->asGrid();
1443 			break;
1444 
1445 		case  2:	// this = blue
1446 			pOverlay[0]	= m_Parameters("OVERLAY_R")->asGrid();
1447 			pOverlay[1]	= m_Parameters("OVERLAY_G")->asGrid();
1448 			break;
1449 		}
1450 
1451 		for(int i=0; i<2; i++)
1452 		{
1453 			if( !SG_Get_Data_Manager().Exists(pOverlay[i]) )
1454 			{
1455 				pOverlay[i]	= NULL;
1456 			}
1457 			else if( pOverlay[i]->Get_Owner() )
1458 			{
1459 				double	Interval	=
1460 					m_pClassify->Get_Metric_Mode() == METRIC_MODE_LOGUP   ?  m_pClassify->Get_Metric_LogFactor() :
1461 					m_pClassify->Get_Metric_Mode() == METRIC_MODE_LOGDOWN ? -m_pClassify->Get_Metric_LogFactor() : 0.;
1462 
1463 				switch( m_Fit_Colors )
1464 				{
1465 				default: Scaler[i].Set_Linear    (pOverlay[i], Interval, m_Parameters("STRETCH_LINEAR.MIN")->asDouble(), m_Parameters("STRETCH_LINEAR.MAX")->asDouble()); break;
1466 				case  1: Scaler[i].Set_StdDev    (pOverlay[i], Interval, m_Parameters("STRETCH_STDDEV"    )->asDouble(), m_Parameters("STRETCH_INRANGE"   )->asBool  ()); break;
1467 				case  2: Scaler[i].Set_Percentile(pOverlay[i], Interval, m_Parameters("STRETCH_PCTL.MIN"  )->asDouble(), m_Parameters("STRETCH_PCTL.MAX"  )->asDouble()); break;
1468 				}
1469 			}
1470 			else if( g_pData->Get(pOverlay[i]) )
1471 			{
1472 				CWKSP_Layer_Classify	*pClassify	= ((CWKSP_Layer *)g_pData->Get(pOverlay[i]))->Get_Classifier();
1473 
1474 				Scaler[i].Create(pClassify->Get_Metric_Minimum(), pClassify->Get_Metric_Maximum(),
1475 					pClassify->Get_Metric_Mode() == METRIC_MODE_LOGUP   ?  pClassify->Get_Metric_LogFactor() :
1476 					pClassify->Get_Metric_Mode() == METRIC_MODE_LOGDOWN ? -pClassify->Get_Metric_LogFactor() : 0.
1477 				);
1478 			}
1479 		}
1480 	}
1481 }
1482 
1483 //---------------------------------------------------------
_Draw_Grid_Nodes(CWKSP_Map_DC & dc_Map,TSG_Grid_Resampling Resampling,int yDC,int axDC,int bxDC,CSG_Grid * pOverlay[2],CSG_Scaler Scaler[2])1484 void CWKSP_Grid::_Draw_Grid_Nodes(CWKSP_Map_DC &dc_Map, TSG_Grid_Resampling Resampling, int yDC, int axDC, int bxDC, CSG_Grid *pOverlay[2], CSG_Scaler Scaler[2])
1485 {
1486 	int	Overlay[3];
1487 
1488 	switch( m_Parameters("OVERLAY_MODE")->asInt() )
1489 	{
1490 	default: Overlay[0] = 0; Overlay[1] = 1; Overlay[2] = 2; break;	// this = r, pOverlay[0] = g, pOverlay[1] = r
1491 	case  1: Overlay[0] = 1; Overlay[1] = 0; Overlay[2] = 2; break;	// this = g, pOverlay[0] = r, pOverlay[1] = b
1492 	case  2: Overlay[0] = 2; Overlay[1] = 0; Overlay[2] = 1; break;	// this = b, pOverlay[0] = r, pOverlay[1] = g
1493 	}
1494 
1495 	double	xMap	= dc_Map.xDC2World(axDC);
1496 	double	yMap	= dc_Map.yDC2World( yDC);
1497 
1498 	for(int xDC=axDC; xDC<=bxDC; xMap+=dc_Map.m_DC2World, xDC++)
1499 	{
1500 		double	Value;
1501 
1502 		if( Get_Grid()->Get_Value(xMap, yMap, Value, Resampling, false, m_pClassify->Get_Mode() == CLASSIFY_RGB) )
1503 		{
1504 			if( m_pClassify->Get_Mode() != CLASSIFY_OVERLAY )
1505 			{
1506 				int  Color;
1507 
1508 				if( m_pClassify->Get_Class_Color_byValue(Value, Color) )
1509 				{
1510 					dc_Map.IMG_Set_Pixel(xDC, yDC, _Get_Shading(xMap, yMap, Color, Resampling));
1511 				}
1512 			}
1513 			else
1514 			{
1515 				BYTE Color[4]; Color[3] = 0;
1516 
1517 				Value = m_pClassify->Get_MetricToRelative(Value);
1518 				Color[Overlay[0]] = Value <= 0. ? 0 : Value >= 1. ? 255 : (BYTE)(255. * Value);
1519 
1520 				Value = pOverlay[0] && pOverlay[0]->Get_Value(xMap, yMap, Value, Resampling) ? Scaler[0].to_Relative(Value) : 1.;
1521 				Color[Overlay[1]] = Value <= 0. ? 0 : Value >= 1. ? 255 : (BYTE)(255. * Value);
1522 
1523 				Value = pOverlay[1] && pOverlay[1]->Get_Value(xMap, yMap, Value, Resampling) ? Scaler[1].to_Relative(Value) : 1.;
1524 				Color[Overlay[2]] = Value <= 0. ? 0 : Value >= 1. ? 255 : (BYTE)(255. * Value);
1525 
1526 				dc_Map.IMG_Set_Pixel(xDC, yDC, _Get_Shading(xMap, yMap, *(int *)Color, Resampling));
1527 			}
1528 		}
1529 	}
1530 }
1531 
1532 //---------------------------------------------------------
_Draw_Grid_Cells(CWKSP_Map_DC & dc_Map)1533 void CWKSP_Grid::_Draw_Grid_Cells(CWKSP_Map_DC &dc_Map)
1534 {
1535 	int	xa	= Get_Grid()->Get_System().Get_xWorld_to_Grid(dc_Map.m_rWorld.Get_XMin()); if( xa <  0                    ) xa = 0;
1536 	int	ya	= Get_Grid()->Get_System().Get_yWorld_to_Grid(dc_Map.m_rWorld.Get_YMin()); if( ya <  0                    ) ya = 0;
1537 	int	xb	= Get_Grid()->Get_System().Get_xWorld_to_Grid(dc_Map.m_rWorld.Get_XMax()); if( xb >= Get_Grid()->Get_NX() ) xb = Get_Grid()->Get_NX() - 1;
1538 	int	yb	= Get_Grid()->Get_System().Get_yWorld_to_Grid(dc_Map.m_rWorld.Get_YMax()); if( yb >= Get_Grid()->Get_NY() ) yb = Get_Grid()->Get_NY() - 1;
1539 
1540 	double	dDC	 = Get_Grid()->Get_Cellsize() * dc_Map.m_World2DC;
1541 
1542 	double	axDC = dc_Map.xWorld2DC(Get_Grid()->Get_System().Get_xGrid_to_World(xa)) + dDC / 2.;
1543 	double	ayDC = dc_Map.yWorld2DC(Get_Grid()->Get_System().Get_yGrid_to_World(ya)) - dDC / 2.;
1544 
1545 	//-----------------------------------------------------
1546 	double	yDC	= ayDC;
1547 
1548 	for(int y=ya, yaDC=(int)(ayDC), ybDC=(int)(ayDC+dDC); y<=yb; y++, ybDC=yaDC, yaDC=(int)(yDC-=dDC))
1549 	{
1550 		double	xDC	= axDC;
1551 
1552 		for(int x=xa, xaDC=(int)(axDC-dDC), xbDC=(int)(axDC); x<=xb; x++, xaDC=xbDC, xbDC=(int)(xDC+=dDC))
1553 		{
1554 			int	Color;
1555 
1556 			if( Get_Grid()->is_InGrid(x, y) && m_pClassify->Get_Class_Color_byValue(Get_Grid()->asDouble(x, y), Color) )
1557 			{
1558 				dc_Map.IMG_Set_Rect(xaDC, yaDC, xbDC, ybDC, _Get_Shading(x, y, Color));
1559 			}
1560 		}
1561 	}
1562 }
1563 
1564 //---------------------------------------------------------
_Set_Shading(double Shade,int & Color)1565 inline void CWKSP_Grid::_Set_Shading(double Shade, int &Color)
1566 {
1567 	switch( m_Shade_Mode )
1568 	{
1569 	default: Shade =      Shade / M_PI_090; break;
1570 	case  1: Shade = 1. - Shade / M_PI_090; break;
1571 	}
1572 
1573 	Shade	= m_Shade_Parms[5] * (Shade - m_Shade_Parms[4]);
1574 
1575 	int	r	= (int)(Shade * SG_GET_R(Color)); if( r < 0 ) r = 0; else if( r > 255 ) r = 255;
1576 	int	g	= (int)(Shade * SG_GET_G(Color)); if( g < 0 ) g = 0; else if( g > 255 ) g = 255;
1577 	int	b	= (int)(Shade * SG_GET_B(Color)); if( b < 0 ) b = 0; else if( b > 255 ) b = 255;
1578 
1579 	Color	= SG_GET_RGB(r, g, b);
1580 }
1581 
1582 //---------------------------------------------------------
_Get_Shading(int x,int y,int Color)1583 inline int CWKSP_Grid::_Get_Shading(int x, int y, int Color)
1584 {
1585 	if( m_Shade_Mode )
1586 	{
1587 		double	s, a;
1588 
1589 		if( Get_Grid()->Get_Gradient(x, y, s, a) )
1590 		{
1591 			s	= M_PI_090 - atan(m_Shade_Parms[0] * tan(s));
1592 
1593 			_Set_Shading(acos(sin(s) * m_Shade_Parms[1] + cos(s) * m_Shade_Parms[2] * cos(a - m_Shade_Parms[3])), Color);
1594 		}
1595 	}
1596 
1597 	if( m_pAlpha )
1598 	{
1599 		double	Alpha;	TSG_Point	p	= Get_Grid()->Get_System().Get_Grid_to_World(x, y);
1600 
1601 		Alpha	= m_pAlpha->Get_Value(p, Alpha) ? (Alpha - m_Alpha[0]) * m_Alpha[1] : 1.;
1602 
1603 		((BYTE *)&Color)[3] = Alpha <= 0. ? 0 : Alpha >= 255. ? 255 : (BYTE)Alpha;
1604 	}
1605 
1606 	return( Color );
1607 }
1608 
1609 //---------------------------------------------------------
_Get_Shading(double x,double y,int Color,TSG_Grid_Resampling Resampling)1610 inline int CWKSP_Grid::_Get_Shading(double x, double y, int Color, TSG_Grid_Resampling Resampling)
1611 {
1612 	if( m_Shade_Mode )
1613 	{
1614 		double	s, a;
1615 
1616 		if( Get_Grid()->Get_Gradient(x, y, s, a, Resampling) )
1617 		{
1618 			s	= M_PI_090 - atan(m_Shade_Parms[0] * tan(s));
1619 
1620 			_Set_Shading(acos(sin(s) * m_Shade_Parms[1] + cos(s) * m_Shade_Parms[2] * cos(a - m_Shade_Parms[3])), Color);
1621 		}
1622 	}
1623 
1624 	if( m_pAlpha )
1625 	{
1626 		double	Alpha;
1627 
1628 		Alpha	= m_pAlpha->Get_Value(x, y, Alpha, Resampling) ? (Alpha - m_Alpha[0]) * m_Alpha[1] : 1.;
1629 
1630 		((BYTE *)&Color)[3] = Alpha <= 0. ? 0 : Alpha >= 255. ? 255 : (BYTE)Alpha;
1631 	}
1632 
1633 	return( Color );
1634 }
1635 
1636 //---------------------------------------------------------
_Draw_Values(CWKSP_Map_DC & dc_Map)1637 void CWKSP_Grid::_Draw_Values(CWKSP_Map_DC &dc_Map)
1638 {
1639 	if(	!m_Parameters("VALUES_SHOW")->asBool() || Get_Grid()->Get_Cellsize() * dc_Map.m_World2DC <= 40 )
1640 	{
1641 		return;
1642 	}
1643 
1644 	//-----------------------------------------------------
1645 	int			ax, ay, bx, by, Decimals, Effect;
1646 	double		axDC, ayDC, dDC;
1647 	wxColour	Effect_Color;
1648 	wxFont		Font;
1649 
1650 	dDC			= Get_Grid()->Get_Cellsize() * dc_Map.m_World2DC;
1651 	Decimals	= m_Parameters("VALUES_DECIMALS")->asInt();
1652 	Font		= Get_Font(m_Parameters("VALUES_FONT"));
1653 	Font.SetPointSize((int)(dDC * m_Parameters("VALUES_SIZE")->asDouble() / 100.));
1654 	dc_Map.dc.SetFont(Font);
1655 	dc_Map.dc.SetTextForeground(Get_Color_asWX(m_Parameters("VALUES_FONT")->asColor()));
1656 
1657 	switch( m_Parameters("VALUES_EFFECT")->asInt() )
1658 	{
1659 	default: Effect	= TEXTEFFECT_NONE       ;	break;
1660 	case  1: Effect	= TEXTEFFECT_FRAME      ;	break;
1661 	case  2: Effect	= TEXTEFFECT_TOP        ;	break;
1662 	case  3: Effect	= TEXTEFFECT_TOPLEFT    ;	break;
1663 	case  4: Effect	= TEXTEFFECT_LEFT       ;	break;
1664 	case  5: Effect	= TEXTEFFECT_BOTTOMLEFT ;	break;
1665 	case  6: Effect	= TEXTEFFECT_BOTTOM     ;	break;
1666 	case  7: Effect	= TEXTEFFECT_BOTTOMRIGHT;	break;
1667 	case  8: Effect	= TEXTEFFECT_RIGHT      ;	break;
1668 	case  9: Effect	= TEXTEFFECT_TOPRIGHT   ;	break;
1669 	}
1670 
1671 	Effect_Color	= m_Parameters("VALUES_EFFECT_COLOR")->asColor();
1672 
1673 	//-------------------------------------------------
1674 	ax		= Get_Grid()->Get_System().Get_xWorld_to_Grid(dc_Map.m_rWorld.Get_XMin());
1675 	ay		= Get_Grid()->Get_System().Get_yWorld_to_Grid(dc_Map.m_rWorld.Get_YMin());
1676 	bx		= Get_Grid()->Get_System().Get_xWorld_to_Grid(dc_Map.m_rWorld.Get_XMax());
1677 	by		= Get_Grid()->Get_System().Get_yWorld_to_Grid(dc_Map.m_rWorld.Get_YMax());
1678 
1679 	if( ax < 0 )	ax	= 0;	if( bx >= Get_Grid()->Get_NX() )	bx	= Get_Grid()->Get_NX() - 1;
1680 	if( ay < 0 )	ax	= 0;	if( by >= Get_Grid()->Get_NY() )	by	= Get_Grid()->Get_NY() - 1;
1681 
1682 	axDC	= dc_Map.xWorld2DC(Get_Grid()->Get_System().Get_xGrid_to_World(ax));
1683 	ayDC	= dc_Map.yWorld2DC(Get_Grid()->Get_System().Get_yGrid_to_World(ay));
1684 
1685 	int	ny	= by - ay;
1686 
1687 	//-------------------------------------------------
1688 	for(int y=0; y<=ny; y++)
1689 	{
1690 		int		x;
1691 		double	xDC, yDC	= ayDC - y * dDC;// dc_Map.m_World2DC;
1692 
1693 		for(x=ax, xDC=axDC; x<=bx; x++, xDC+=dDC)
1694 		{
1695 			if( Get_Grid()->is_InGrid(x, ay + y) )
1696 			{
1697 				double	Value	= Get_Grid()->asDouble(x, ay + y);
1698 
1699 				switch( m_pClassify->Get_Mode() )
1700 				{
1701 				case CLASSIFY_RGB:
1702 					Draw_Text(dc_Map.dc, TEXTALIGN_CENTER, (int)xDC, (int)yDC, wxString::Format(
1703 						"R%03d G%03d B%03d", SG_GET_R((int)Value), SG_GET_G((int)Value), SG_GET_B((int)Value)
1704 					), Effect, Effect_Color);
1705 					break;
1706 
1707 				default:
1708 					Draw_Text(dc_Map.dc, TEXTALIGN_CENTER, (int)xDC, (int)yDC, wxString::Format(
1709 						"%.*f", Decimals, Value
1710 					), Effect, Effect_Color);
1711 					break;
1712 				}
1713 			}
1714 		}
1715 	}
1716 }
1717 
1718 //---------------------------------------------------------
_Draw_Edit(CWKSP_Map_DC & dc_Map)1719 void CWKSP_Grid::_Draw_Edit(CWKSP_Map_DC &dc_Map)
1720 {
1721 	if( m_Edit_Attributes.Get_Count() > 0 )
1722 	{
1723 		CSG_Rect	r(
1724 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_xGrid_to_World(m_xSel),
1725 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_yGrid_to_World(m_ySel),
1726 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_xGrid_to_World(m_xSel + m_Edit_Attributes.Get_Field_Count() - 1),
1727 			-Get_Grid()->Get_Cellsize() / 2. + Get_Grid()->Get_System().Get_yGrid_to_World(m_ySel + m_Edit_Attributes.Get_Count())
1728 		);
1729 
1730 		TSG_Point_Int	a(dc_Map.World2DC(r.Get_TopLeft    ()));
1731 		TSG_Point_Int	b(dc_Map.World2DC(r.Get_BottomRight()));
1732 
1733 		a.x	-= 1;
1734 		b.x	-= 1;
1735 		a.y	-= 1;
1736 		b.y	-= 1;
1737 
1738 		dc_Map.dc.SetPen(wxPen(wxColour(255, 0, 0), 2, wxPENSTYLE_SOLID));
1739 		dc_Map.dc.DrawLine(a.x, a.y, a.x, b.y);
1740 		dc_Map.dc.DrawLine(a.x, b.y, b.x, b.y);
1741 		dc_Map.dc.DrawLine(b.x, b.y, b.x, a.y);
1742 		dc_Map.dc.DrawLine(a.x, a.y, b.x, a.y);
1743 	}
1744 }
1745 
1746 
1747 ///////////////////////////////////////////////////////////
1748 //														 //
1749 //														 //
1750 //														 //
1751 ///////////////////////////////////////////////////////////
1752 
1753 //---------------------------------------------------------
1754