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_Shapes.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 <saga_gdi/sgdi_helper.h>
52
53 #include "res_commands.h"
54 #include "res_dialogs.h"
55
56 #include "helper.h"
57
58 #include "active.h"
59
60 #include "wksp_layer_classify.h"
61
62 #include "wksp_data_manager.h"
63
64 #include "wksp_shapes.h"
65 #include "wksp_table.h"
66
67 #include "data_source_pgsql.h"
68
69
70 ///////////////////////////////////////////////////////////
71 // //
72 // //
73 // //
74 ///////////////////////////////////////////////////////////
75
76 //---------------------------------------------------------
CWKSP_Shapes(CSG_Shapes * pShapes)77 CWKSP_Shapes::CWKSP_Shapes(CSG_Shapes *pShapes)
78 : CWKSP_Layer(pShapes)
79 {
80 m_pTable = new CWKSP_Table(pShapes);
81
82 m_fInfo = -1;
83
84 m_Edit_Shapes.Create(pShapes->Get_Type());
85 m_Edit_pShape = NULL;
86
87 m_Edit_Attributes.Destroy();
88 m_Edit_Attributes.Add_Field(_TL("Name" ), SG_DATATYPE_String);
89 m_Edit_Attributes.Add_Field(_TL("Value"), SG_DATATYPE_String);
90
91 m_Edit_Color = *wxBLACK;
92 m_Edit_bGleam = true;
93 m_Edit_Mode = EDIT_SHAPE_MODE_Normal;
94
95 m_Sel_Color = *wxRED;
96
97 m_bVertices = 0;
98 }
99
100 //---------------------------------------------------------
~CWKSP_Shapes(void)101 CWKSP_Shapes::~CWKSP_Shapes(void)
102 {
103 delete(m_pTable);
104 }
105
106
107 ///////////////////////////////////////////////////////////
108 // //
109 ///////////////////////////////////////////////////////////
110
111 //---------------------------------------------------------
Get_Description(void)112 wxString CWKSP_Shapes::Get_Description(void)
113 {
114 wxString s;
115
116 //-----------------------------------------------------
117 s += wxString::Format("<h4>%s</h4>", _TL("Shapes"));
118
119 s += "<table border=\"0\">";
120
121 DESC_ADD_STR(_TL("Name" ), m_pObject->Get_Name());
122 DESC_ADD_STR(_TL("Description" ), m_pObject->Get_Description());
123
124 if( SG_File_Exists(m_pObject->Get_File_Name(false)) )
125 {
126 DESC_ADD_STR(_TL("File" ), m_pObject->Get_File_Name(false));
127
128 if( m_pObject->Get_MetaData()("GDAL_DRIVER") )
129 DESC_ADD_STR(_TL("Driver" ), m_pObject->Get_MetaData()["GDAL_DRIVER"].Get_Content().c_str());
130 }
131 else if( m_pObject->Get_MetaData_DB().Get_Children_Count() )
132 {
133 DESC_ADD_STR(_TL("File" ), m_pObject->Get_File_Name(false));
134 }
135 else
136 {
137 DESC_ADD_STR(_TL("File" ), _TL("memory"));
138 }
139
140 DESC_ADD_STR (_TL("Modified" ), m_pObject->is_Modified() ? _TL("yes") : _TL("no"));
141 DESC_ADD_STR (_TL("Projection" ), m_pObject->Get_Projection().Get_Description().c_str());
142 DESC_ADD_FLT (_TL("West" ), Get_Shapes()->Get_Extent().Get_XMin ());
143 DESC_ADD_FLT (_TL("East" ), Get_Shapes()->Get_Extent().Get_XMax ());
144 DESC_ADD_FLT (_TL("West-East" ), Get_Shapes()->Get_Extent().Get_XRange());
145 DESC_ADD_FLT (_TL("South" ), Get_Shapes()->Get_Extent().Get_YMin ());
146 DESC_ADD_FLT (_TL("North" ), Get_Shapes()->Get_Extent().Get_YMax ());
147 DESC_ADD_FLT (_TL("South-North" ), Get_Shapes()->Get_Extent().Get_YRange());
148 DESC_ADD_STR (_TL("Type" ), SG_Get_ShapeType_Name(Get_Shapes()->Get_Type()).c_str());
149 DESC_ADD_STR (_TL("Vertex Type" ), Get_Shapes()->Get_Vertex_Type() == 0 ? _TL("X, Y") : Get_Shapes()->Get_Vertex_Type() == 1 ? _TL("X, Y, Z") : _TL("X, Y, Z, M"));
150 DESC_ADD_INT (_TL("Number of Shapes"), Get_Shapes()->Get_Count());
151 DESC_ADD_SIZET(_TL("Selected" ), Get_Shapes()->Get_Selection_Count());
152 DESC_ADD_STR (_TL("File Encoding" ), Get_Shapes()->Get_File_Encoding() ? SG_T("UTF-8") : SG_T("ANSI"));
153
154 s += "</table>";
155
156 s += Get_TableInfo_asHTML(Get_Shapes());
157
158 //-----------------------------------------------------
159 // s += wxString::Format(wxT("<hr><b>%s</b><font size=\"-1\">"), _TL("Data History"));
160 // s += Get_Shapes()->Get_History().Get_HTML();
161 // s += wxString::Format(wxT("</font"));
162
163 return( s );
164 }
165
166 //---------------------------------------------------------
Get_Menu(void)167 wxMenu * CWKSP_Shapes::Get_Menu(void)
168 {
169 wxMenu *pMenu = new wxMenu(m_pObject->Get_Name());
170
171 CMD_Menu_Add_Item(pMenu, false, ID_CMD_WKSP_ITEM_CLOSE);
172 CMD_Menu_Add_Item(pMenu, false, ID_CMD_SHAPES_SHOW);
173
174 pMenu->AppendSeparator();
175 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVE);
176 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVEAS);
177
178 if( PGSQL_has_Connections() )
179 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_SAVETODB);
180
181 if( m_pObject->is_File_Native() && m_pObject->is_Modified() )
182 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_RELOAD);
183
184 if( m_pObject->is_File_Native() )
185 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_DEL_FILES);
186
187 pMenu->AppendSeparator();
188 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_PROJECTION);
189
190 if( m_pObject->Get_MetaData().Get_Children_Count() > 0 )
191 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_METADATA);
192
193 pMenu->AppendSeparator();
194 CMD_Menu_Add_Item(pMenu, true, ID_CMD_SHAPES_HISTOGRAM);
195
196 pMenu->AppendSeparator();
197 CMD_Menu_Add_Item(pMenu, false, ID_CMD_SHAPES_SET_LUT);
198 CMD_Menu_Add_Item(pMenu, false, ID_CMD_DATA_CLASSIFY_IMPORT);
199 CMD_Menu_Add_Item(pMenu, false, ID_CMD_WKSP_ITEM_SETTINGS_COPY);
200
201 pMenu->AppendSeparator();
202 wxMenu *pTable = new wxMenu(_TL("Attributes"));
203 CMD_Menu_Add_Item(pTable, true, ID_CMD_TABLE_SHOW);
204 CMD_Menu_Add_Item(pTable, true, ID_CMD_TABLE_DIAGRAM);
205 CMD_Menu_Add_Item(pTable, false, ID_CMD_TABLE_SCATTERPLOT);
206 CMD_Menu_Add_Item(pTable, false, ID_CMD_SHAPES_SAVE_ATTRIBUTES);
207 pMenu->Append(ID_CMD_WKSP_FIRST, _TL("Attributes"), pTable);
208
209 pMenu->Append(ID_CMD_WKSP_FIRST, _TL("Edit"), Edit_Get_Menu());
210
211 return( pMenu );
212 }
213
214
215 ///////////////////////////////////////////////////////////
216 // //
217 ///////////////////////////////////////////////////////////
218
219 //---------------------------------------------------------
On_Command(int Cmd_ID)220 bool CWKSP_Shapes::On_Command(int Cmd_ID)
221 {
222 switch( Cmd_ID )
223 {
224 default:
225 return( CWKSP_Layer::On_Command(Cmd_ID) );
226
227 //-----------------------------------------------------
228 case ID_CMD_SHAPES_SET_LUT : _LUT_Create (); break;
229 case ID_CMD_DATA_CLASSIFY_IMPORT : _LUT_Import (); break;
230 case ID_CMD_SHAPES_HISTOGRAM : Histogram_Toggle(); break;
231
232 //-----------------------------------------------------
233 case ID_CMD_SHAPES_EDIT_SHAPE : _Edit_Shape (); break;
234 case ID_CMD_SHAPES_EDIT_ADD_SHAPE: _Edit_Shape_Add(); break;
235 case ID_CMD_SHAPES_EDIT_DEL_SHAPE: _Edit_Shape_Del(); break;
236 case ID_CMD_SHAPES_EDIT_ADD_PART : _Edit_Part_Add (); break;
237 case ID_CMD_SHAPES_EDIT_DEL_PART : _Edit_Part_Del (); break;
238 case ID_CMD_SHAPES_EDIT_DEL_POINT: _Edit_Point_Del(); break;
239 case ID_CMD_SHAPES_EDIT_MERGE : _Edit_Merge (); break;
240 case ID_CMD_SHAPES_EDIT_SPLIT : _Edit_Split (); break;
241 case ID_CMD_SHAPES_EDIT_MOVE : _Edit_Move (); break;
242
243 case ID_CMD_SHAPES_EDIT_SEL_CLEAR:
244 Get_Shapes()->Select();
245 Update_Views();
246 break;
247
248 case ID_CMD_SHAPES_EDIT_SEL_INVERT:
249 Get_Shapes()->Inv_Selection();
250 Update_Views();
251 break;
252
253 //-----------------------------------------------------
254 case ID_CMD_TABLE_SHOW : m_pTable->Toggle_View (); break;
255 case ID_CMD_TABLE_DIAGRAM: m_pTable->Toggle_Diagram(); break;
256
257 case ID_CMD_TABLE_SCATTERPLOT:
258 Add_ScatterPlot();
259 break;
260
261 case ID_CMD_SHAPES_SAVE_ATTRIBUTES:
262 {
263 wxString File(m_pObject->Get_File_Name());
264
265 if( DLG_Save(File, ID_DLG_TABLE_SAVE) )
266 {
267 CSG_Table Table(*((CSG_Table *)m_pObject));
268
269 Table.Save(&File);
270 }
271 }
272 break;
273 }
274
275 return( true );
276 }
277
278 //---------------------------------------------------------
On_Command_UI(wxUpdateUIEvent & event)279 bool CWKSP_Shapes::On_Command_UI(wxUpdateUIEvent &event)
280 {
281 switch( event.GetId() )
282 {
283 default:
284 return( CWKSP_Layer::On_Command_UI(event) );
285
286 case ID_CMD_SHAPES_EDIT_SHAPE:
287 event.Enable(Get_Shapes()->Get_Selection_Count() > 0 || m_Edit_pShape != NULL);
288 event.Check(m_Edit_pShape != NULL);
289 break;
290
291 case ID_CMD_SHAPES_EDIT_ADD_SHAPE:
292 event.Enable(m_Edit_pShape == NULL);
293 break;
294
295 case ID_CMD_SHAPES_EDIT_DEL_SHAPE:
296 event.Enable(Get_Shapes()->Get_Selection_Count() > 0 && m_Edit_pShape == NULL);
297 break;
298
299 case ID_CMD_SHAPES_EDIT_ADD_PART:
300 event.Enable(m_Edit_pShape != NULL);
301 break;
302
303 case ID_CMD_SHAPES_EDIT_DEL_PART:
304 event.Enable(m_Edit_pShape != NULL && m_Edit_iPart >= 0);
305 break;
306
307 case ID_CMD_SHAPES_EDIT_DEL_POINT:
308 event.Enable(m_Edit_pShape != NULL && m_Edit_iPart >= 0 && m_Edit_iPoint >= 0);
309 break;
310
311 case ID_CMD_SHAPES_EDIT_SEL_CLEAR:
312 event.Enable(m_Edit_pShape == NULL && Get_Shapes()->Get_Selection_Count() > 0);
313 break;
314
315 case ID_CMD_SHAPES_EDIT_SEL_INVERT:
316 event.Enable(m_Edit_pShape == NULL);
317 break;
318
319 case ID_CMD_TABLE_SHOW:
320 event.Check(m_pTable->Get_View() != NULL);
321 break;
322
323 case ID_CMD_TABLE_DIAGRAM:
324 event.Check(m_pTable->Get_Diagram() != NULL);
325 break;
326
327 case ID_CMD_SHAPES_HISTOGRAM:
328 event.Check(m_pHistogram != NULL);
329 break;
330
331 case ID_CMD_SHAPES_EDIT_MOVE:
332 event.Check(m_Edit_Mode == EDIT_SHAPE_MODE_Move);
333 break;
334 }
335
336 return( true );
337 }
338
339
340 ///////////////////////////////////////////////////////////
341 // //
342 ///////////////////////////////////////////////////////////
343
344 //---------------------------------------------------------
On_Create_Parameters(void)345 void CWKSP_Shapes::On_Create_Parameters(void)
346 {
347 CWKSP_Layer::On_Create_Parameters();
348
349 //-----------------------------------------------------
350 // General...
351
352 m_Parameters.Add_Choice("NODE_GENERAL",
353 "INFO_ATTRIB" , _TL("Additional Information"),
354 _TL("Field that provides file paths to additional record information (HTML formatted), either absolute or relative to this data set."),
355 _TL("<default>")
356 );
357
358 //-----------------------------------------------------
359 // Display...
360
361 m_Parameters.Add_Parameters("NODE_DISPLAY",
362 "DISPLAY_CHART" , _TL("Chart"), _TL("")
363 );
364
365 //-----------------------------------------------------
366 // Classification...
367
368 m_Parameters.Add_Bool("NODE_COLORS",
369 "NODATA_SHOW" , _TL("Show No-Data"), _TL(""), true
370 );
371
372 m_Parameters.Add_Color("NODATA_SHOW",
373 "NODATA_COLOR" , _TL("Color"), _TL(""), SG_COLOR_GREY_LIGHT
374 );
375
376 //-----------------------------------------------------
377 // Label...
378
379 m_Parameters.Add_Choice("NODE_LABEL",
380 "LABEL_ATTRIB" , _TL("Attribute"),
381 _TL(""),
382 _TL("<default>")
383 );
384
385 m_Parameters.Add_Font("LABEL_ATTRIB",
386 "LABEL_ATTRIB_FONT" , _TL("Font"),
387 _TL("")
388 );
389
390 m_Parameters.Add_Choice("LABEL_ATTRIB",
391 "LABEL_ATTRIB_PREC" , _TL("Numerical Precision"),
392 _TL(""),
393 CSG_String::Format("%s|%s|%s",
394 _TL("fit to value"),
395 _TL("standard"),
396 SG_T("0|0.1|0.12|0.123|0.1234|0.12345|0.1234567|0.12345678|0.123456789|0.1234567890|0.12345678901|0.123456789012|0.1234567890123|0.12345678901234|0.123456789012345|0.1234567890123456|0.12345678901234567|0.123456789012345678|0.1234567890123456789|0.12345678901234567890")
397 ), 0
398 );
399
400 m_Parameters.Add_Choice("LABEL_ATTRIB",
401 "LABEL_ATTRIB_SIZE_TYPE", _TL("Size relates to..."),
402 _TL(""),
403 CSG_String::Format("%s|%s|",
404 _TL("Screen"),
405 _TL("Map Units")
406 ), 0
407 );
408
409 m_Parameters.Add_Choice("LABEL_ATTRIB",
410 "LABEL_ATTRIB_EFFECT" , _TL("Boundary Effect"),
411 _TL(""),
412 CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
413 _TL("none"),
414 _TL("full frame"),
415 _TL("top"),
416 _TL("top left"),
417 _TL("left"),
418 _TL("bottom left"),
419 _TL("bottom"),
420 _TL("bottom right"),
421 _TL("right"),
422 _TL("top right")
423 ), 1
424 );
425
426 m_Parameters.Add_Color("LABEL_ATTRIB_EFFECT",
427 "LABEL_ATTRIB_EFFECT_COLOR" , _TL("Color"),
428 _TL(""),
429 SG_GET_RGB(255, 255, 255)
430 );
431
432 m_Parameters.Add_Int("LABEL_ATTRIB_EFFECT",
433 "LABEL_ATTRIB_EFFECT_SIZE" , _TL("Size"),
434 _TL(""),
435 1, 1, true
436 );
437
438 m_Parameters.Add_Choice("LABEL_ATTRIB",
439 "LABEL_ATTRIB_SIZE_BY" , _TL("Size by Attribute"),
440 _TL(""),
441 _TL("<default>")
442 );
443
444 m_Parameters.Add_Double("LABEL_ATTRIB_SIZE_BY",
445 "LABEL_ATTRIB_SIZE" , _TL("Default Size"),
446 _TL(""),
447 100., 0., true
448 );
449
450 //-----------------------------------------------------
451 // Selection...
452
453 m_Parameters.Add_Color("NODE_SELECTION",
454 "SEL_COLOR" , _TL("Color"),
455 _TL(""),
456 m_Sel_Color.GetRGB()
457 );
458
459 //-----------------------------------------------------
460 // Edit...
461
462 m_Parameters.Add_Color("NODE_EDIT",
463 "EDIT_COLOR" , _TL("Color"),
464 _TL(""),
465 m_Edit_Color.GetRGB()
466 );
467
468 m_Parameters.Add_Bool("NODE_EDIT",
469 "EDIT_GLEAM" , _TL("Gleam"),
470 _TL(""),
471 m_Edit_bGleam
472 );
473
474 m_Parameters.Add_Shapes_List("NODE_EDIT",
475 "EDIT_SNAP_LIST", _TL("Snap to..."),
476 _TL(""),
477 PARAMETER_INPUT
478 )->asShapesList()->Add_Item(m_pObject);
479
480 m_Parameters.Add_Int("EDIT_SNAP_LIST",
481 "EDIT_SNAP_DIST", _TL("Snap Distance"),
482 _TL("snap distance in screen units (pixels)"),
483 10, 0, true
484 );
485
486 m_Parameters("LUT")->asTable()->Set_Field_Type(LUT_MIN, SG_DATATYPE_String);
487 m_Parameters("LUT")->asTable()->Set_Field_Type(LUT_MAX, SG_DATATYPE_String);
488 }
489
490
491 ///////////////////////////////////////////////////////////
492 // //
493 ///////////////////////////////////////////////////////////
494
495 //---------------------------------------------------------
On_DataObject_Changed(void)496 void CWKSP_Shapes::On_DataObject_Changed(void)
497 {
498 AttributeList_Set(m_Parameters("LUT_ATTRIB" ), false);
499 AttributeList_Set(m_Parameters("METRIC_ATTRIB" ), false);
500 AttributeList_Set(m_Parameters("METRIC_NORMAL" ), true );
501 AttributeList_Set(m_Parameters("LABEL_ATTRIB" ), true );
502 AttributeList_Set(m_Parameters("LABEL_ATTRIB_SIZE_BY"), true );
503 AttributeList_Set(m_Parameters("INFO_ATTRIB" ), true );
504
505 _Chart_Set_Options();
506
507 //-----------------------------------------------------
508 CWKSP_Layer::On_DataObject_Changed();
509
510 m_pTable->DataObject_Changed();
511 }
512
513 //---------------------------------------------------------
On_Parameters_Changed(void)514 void CWKSP_Shapes::On_Parameters_Changed(void)
515 {
516 CWKSP_Layer::On_Parameters_Changed();
517
518 //-----------------------------------------------------
519 switch( m_Parameters("COLORS_TYPE")->asInt() )
520 {
521 default: // CLASSIFY_SINGLE
522 m_fValue = -1;
523 m_fNormal = -1;
524 break;
525
526 case 1: // CLASSIFY_LUT
527 m_fValue = m_Parameters("LUT_ATTRIB" )->asInt(); if( m_fValue >= Get_Shapes()->Get_Field_Count() ) { m_fValue = -1; }
528 m_fNormal = -1;
529
530 {
531 TSG_Data_Type Type = SG_Data_Type_is_Numeric(Get_Shapes()->Get_Field_Type(m_Parameters("LUT_ATTRIB")->asInt())) ? SG_DATATYPE_Double : SG_DATATYPE_String;
532
533 m_Parameters("LUT")->asTable()->Set_Field_Type(LUT_MIN, Type);
534 m_Parameters("LUT")->asTable()->Set_Field_Type(LUT_MAX, Type);
535 }
536 break;
537
538 case 2: // CLASSIFY_DISCRETE
539 case 3: // CLASSIFY_GRADUATED
540 m_fValue = m_Parameters("METRIC_ATTRIB")->asInt(); if( m_fValue >= Get_Shapes()->Get_Field_Count() ) { m_fValue = -1; }
541 m_fNormal = m_Parameters("METRIC_NORMAL")->asInt(); if( m_fNormal >= Get_Shapes()->Get_Field_Count() ) { m_fNormal = -1; }
542 m_dNormal = m_Parameters("METRIC_NORFMT")->asInt() == 0 ? 1. : 100.;
543 break;
544 }
545
546 if( m_fValue < 0 )
547 {
548 m_pClassify->Set_Mode(CLASSIFY_SINGLE);
549 }
550
551 m_pClassify->Set_Unique_Color(m_pClassify->Get_Mode() == CLASSIFY_SINGLE
552 ? m_Parameters("SINGLE_COLOR")->asColor()
553 : m_Parameters("NODATA_COLOR")->asColor()
554 );
555
556 m_bNoData = m_Parameters("NODATA_SHOW")->asBool();
557
558 //-----------------------------------------------------
559 int fInfo = m_Parameters("INFO_ATTRIB")->asInt();
560
561 if( fInfo >= Get_Shapes()->Get_Field_Count() )
562 {
563 fInfo = -1;
564 }
565
566 if( m_fInfo != fInfo )
567 {
568 m_fInfo = fInfo;
569
570 if( g_pActive->Get_Active() == this )
571 {
572 g_pActive->Update_Info();
573 }
574 }
575
576 //-----------------------------------------------------
577 if( (m_fLabel = m_Parameters("LABEL_ATTRIB")->asInt()) >= Get_Shapes()->Get_Field_Count() )
578 {
579 m_fLabel = -1;
580 }
581
582 m_Label_Eff_Color = m_Parameters("LABEL_ATTRIB_EFFECT_COLOR")->asColor();
583 m_Label_Eff_Size = m_Parameters("LABEL_ATTRIB_EFFECT_SIZE" )->asInt ();
584 m_Label_Prec = m_Parameters("LABEL_ATTRIB_PREC" )->asInt ();
585
586 switch( m_Label_Prec )
587 {
588 case 0: m_Label_Prec = -m_Parameters("TABLE_FLT_DECIMALS")->asInt(); break;
589 case 1: m_Label_Prec = -99; break;
590 default: m_Label_Prec -= 2; break;
591 }
592
593 switch( m_Parameters("LABEL_ATTRIB_EFFECT")->asInt() )
594 {
595 default: m_Label_Eff = TEXTEFFECT_NONE ; break;
596 case 1: m_Label_Eff = TEXTEFFECT_FRAME ; break;
597 case 2: m_Label_Eff = TEXTEFFECT_TOP ; break;
598 case 3: m_Label_Eff = TEXTEFFECT_TOPLEFT ; break;
599 case 4: m_Label_Eff = TEXTEFFECT_LEFT ; break;
600 case 5: m_Label_Eff = TEXTEFFECT_BOTTOMLEFT ; break;
601 case 6: m_Label_Eff = TEXTEFFECT_BOTTOM ; break;
602 case 7: m_Label_Eff = TEXTEFFECT_BOTTOMRIGHT; break;
603 case 8: m_Label_Eff = TEXTEFFECT_RIGHT ; break;
604 case 9: m_Label_Eff = TEXTEFFECT_TOPRIGHT ; break;
605 }
606
607 //-----------------------------------------------------
608 _Chart_Get_Options();
609 }
610
611
612 ///////////////////////////////////////////////////////////
613 // //
614 ///////////////////////////////////////////////////////////
615
616 //---------------------------------------------------------
Set_Metrics(int zField,int nField,int nType)617 bool CWKSP_Shapes::Set_Metrics(int zField, int nField, int nType)
618 {
619 if( zField >= 0 && zField < Get_Shapes()->Get_Field_Count() )
620 {
621 if( nField < Get_Shapes()->Get_Field_Count() )
622 {
623 m_Metrics.Create();
624
625 for(int i=0; i<Get_Shapes()->Get_Count(); i++)
626 {
627 double z = Get_Shapes()->Get_Record(i)->asDouble(zField);
628 double n = Get_Shapes()->Get_Record(i)->asDouble(nField) / (nType == 0 ? 1. : 100.);
629
630 if( !Get_Shapes()->is_NoData_Value(z) && !Get_Shapes()->is_NoData_Value(n) && n != 0. )
631 {
632 m_Metrics.Add_Value(z / n);
633 }
634 }
635 }
636 else
637 {
638 m_Metrics.Create(Get_Shapes()->Get_Statistics(zField));
639 }
640
641 return( true );
642 }
643
644 return( false );
645 }
646
647
648 ///////////////////////////////////////////////////////////
649 // //
650 ///////////////////////////////////////////////////////////
651
652 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter,int Flags)653 int CWKSP_Shapes::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter, int Flags)
654 {
655 //-----------------------------------------------------
656 if( pParameters->Cmp_Identifier("CLASSIFY") )
657 {
658 if( Flags & PARAMETER_CHECK_ENABLE )
659 {
660 if( pParameter->Cmp_Identifier("METHOD") )
661 {
662 pParameters->Set_Enabled("COUNT" , pParameter->asInt() != 0);
663 pParameters->Set_Enabled("COUNTMAX", pParameter->asInt() == 0);
664 }
665 }
666
667 return( CWKSP_Layer::On_Parameter_Changed(pParameters, pParameter, Flags) );
668 }
669
670 //-----------------------------------------------------
671 if( Flags & PARAMETER_CHECK_VALUES )
672 {
673 if( pParameter->Cmp_Identifier("COLORS_TYPE" )
674 || pParameter->Cmp_Identifier("METRIC_ATTRIB")
675 || pParameter->Cmp_Identifier("METRIC_NORMAL")
676 || pParameter->Cmp_Identifier("METRIC_NORFMT") )
677 {
678 Set_Metrics(
679 pParameters->Get_Parameter("METRIC_ATTRIB")->asInt(),
680 pParameters->Get_Parameter("METRIC_NORMAL")->asInt(),
681 pParameters->Get_Parameter("METRIC_NORFMT")->asInt()
682 );
683
684 pParameters->Get_Parameter("METRIC_ZRANGE")->asRange()->Set_Range(
685 m_Metrics.Get_Minimum(),
686 m_Metrics.Get_Maximum()
687 );
688 }
689
690 if( pParameter->Cmp_Identifier("METRIC_NORMAL") )
691 {
692 pParameters->Set_Enabled("METRIC_NORFMT", pParameter->asInt() >= 0 && pParameter->asInt() < Get_Shapes()->Get_Field_Count());
693 }
694
695 if( pParameter->Cmp_Identifier("LUT_ATTRIB")
696 && pParameter->asInt() >= 0 && pParameter->asInt() < Get_Shapes()->Get_Field_Count() )
697 {
698 TSG_Data_Type Type = SG_Data_Type_is_Numeric(Get_Shapes()->Get_Field_Type(pParameter->asInt()))
699 ? SG_DATATYPE_Double : SG_DATATYPE_String;
700
701 pParameters->Get_Parameter("LUT")->asTable()->Set_Field_Type(LUT_MIN, Type);
702 pParameters->Get_Parameter("LUT")->asTable()->Set_Field_Type(LUT_MAX, Type);
703 }
704 }
705
706 //-----------------------------------------------------
707 if( Flags & PARAMETER_CHECK_ENABLE )
708 {
709 if( pParameter->Cmp_Identifier("COLORS_TYPE") )
710 {
711 pParameters->Set_Enabled("NODATA_SHOW" , pParameter->asInt() > 0); // not 'single symbol'
712 }
713
714 if( pParameter->Cmp_Identifier("NODATA_SHOW") )
715 {
716 pParameters->Set_Enabled("NODATA_COLOR" , pParameter->asBool());
717 }
718
719 if( pParameter->Cmp_Identifier("METRIC_ATTRIB") )
720 {
721 pParameters->Set_Enabled("METRIC_NORMAL", pParameter->asInt() >= 0);
722 }
723
724 if( pParameter->Cmp_Identifier("OUTLINE") )
725 {
726 pParameters->Set_Enabled("OUTLINE_COLOR", pParameter->asBool());
727 pParameters->Set_Enabled("OUTLINE_SIZE" , pParameter->asBool());
728 }
729
730 if( pParameter->Cmp_Identifier("LABEL_ATTRIB") )
731 {
732 bool Value = pParameter->asInt() < Get_Shapes()->Get_Field_Count();
733
734 pParameters->Set_Enabled("LABEL_ATTRIB_FONT" , Value);
735 pParameters->Set_Enabled("LABEL_ATTRIB_SIZE_TYPE", Value);
736 pParameters->Set_Enabled("LABEL_ATTRIB_PREC" , Value);
737 pParameters->Set_Enabled("LABEL_ATTRIB_SIZE_BY" , Value);
738 pParameters->Set_Enabled("LABEL_ATTRIB_EFFECT" , Value);
739 }
740
741 if( pParameter->Cmp_Identifier("LABEL_ATTRIB_SIZE_TYPE")
742 || pParameter->Cmp_Identifier("LABEL_ATTRIB_SIZE_BY" ) )
743 {
744 bool Value = pParameters->Get_Parameter("LABEL_ATTRIB_SIZE_TYPE")->asInt() != 0
745 || pParameters->Get_Parameter("LABEL_ATTRIB_SIZE_BY" )->asInt() < Get_Shapes()->Get_Field_Count();
746
747 pParameters->Set_Enabled("LABEL_ATTRIB_SIZE", Value);
748 }
749
750 if( pParameter->Cmp_Identifier("LABEL_ATTRIB_EFFECT") )
751 {
752 bool Value = pParameter->asInt() > 0;
753
754 pParameters->Set_Enabled("LABEL_ATTRIB_EFFECT_COLOR", Value);
755 }
756
757 if( pParameter->Cmp_Identifier("EDIT_SNAP_LIST") )
758 {
759 pParameters->Set_Enabled("EDIT_SNAP_DIST", pParameter->asList()->Get_Item_Count() > 0);
760 }
761
762 if( pParameters->Cmp_Identifier("DISPLAY_CHART") )
763 {
764 CSG_String s(pParameter->Get_Identifier());
765
766 if( s.Find("FIELD_") == 0 )
767 {
768 s.Replace("FIELD_", "COLOR_");
769
770 pParameters->Set_Enabled(s, pParameter->asBool());
771 }
772 }
773 }
774
775 //-----------------------------------------------------
776 return( CWKSP_Layer::On_Parameter_Changed(pParameters, pParameter, Flags) );
777 }
778
779 //---------------------------------------------------------
On_Update_Views(void)780 void CWKSP_Shapes::On_Update_Views(void)
781 {
782 m_pTable->Update_Views();
783 }
784
785
786 ///////////////////////////////////////////////////////////
787 // //
788 ///////////////////////////////////////////////////////////
789
790 //---------------------------------------------------------
_LUT_Create(void)791 void CWKSP_Shapes::_LUT_Create(void)
792 {
793 //-----------------------------------------------------
794 if( Get_Shapes()->Get_Field_Count() <= 0 || Get_Shapes()->Get_Count() < 1 )
795 {
796 DLG_Message_Show(_TL("Function failed because no attributes are available"), _TL("Classify"));
797
798 return;
799 }
800
801 //-----------------------------------------------------
802 static CSG_Parameters PStatic;
803
804 if( PStatic.Get_Count() == 0 )
805 {
806 PStatic.Create(_TL("Classify"), _TL(""), SG_T("CLASSIFY"));
807 PStatic.Add_Choice("", "FIELD" , _TL("Attribute" ), _TL(""), "");
808 PStatic.Add_Colors("", "COLORS" , _TL("Colors" ), _TL(""));
809 PStatic.Add_Int ("", "COUNT" , _TL("Number of Classes" ), _TL(""), 10, 1, true);
810 PStatic.Add_Int ("", "COUNTMAX", _TL("Maximum Number of Classes"), _TL(""), 1000, 1, true);
811 PStatic.Add_Choice("", "METHOD" , _TL("Classification" ), _TL(""),
812 CSG_String::Format("%s|%s|%s|%s",
813 _TL("unique values"),
814 _TL("equal intervals"),
815 _TL("quantiles"),
816 _TL("natural breaks")
817 ), 0
818 );
819 }
820
821 AttributeList_Set(PStatic("FIELD"), false);
822
823 CSG_Parameters Parameters(this, _TL("Classify"), _TL(""), SG_T("CLASSIFY"));
824
825 Parameters.Assign_Parameters(&PStatic);
826
827 Parameters.Set_Callback_On_Parameter_Changed(&Parameter_Callback);
828
829 if( !DLG_Parameters(&Parameters) )
830 {
831 return;
832 }
833
834 PStatic.Assign_Values(&Parameters);
835
836 //-----------------------------------------------------
837 DataObject_Changed();
838
839 int Field = Parameters("FIELD")->asInt();
840
841 int Method = SG_Data_Type_is_Numeric(Get_Shapes()->Get_Field_Type(Field)) ? Parameters("METHOD")->asInt() : 0;
842
843 CSG_Colors Colors(*Parameters("COLORS")->asColors());
844
845 if( Method != 0 )
846 {
847 Colors.Set_Count(Parameters("COUNT")->asInt());
848 }
849
850 CSG_Table Classes(m_Parameters("LUT")->asTable());
851
852 switch( Method )
853 {
854 //-----------------------------------------------------
855 case 0: // unique values
856 {
857 TSG_Data_Type Type = SG_Data_Type_is_Numeric(Get_Shapes()->Get_Field_Type(Field))
858 ? SG_DATATYPE_Double : SG_DATATYPE_String;
859
860 Classes.Set_Field_Type(LUT_MIN, Type);
861 Classes.Set_Field_Type(LUT_MAX, Type);
862
863 CSG_Unique_String_Statistics s;
864
865 int maxClasses = Parameters("COUNTMAX")->asInt();
866
867 for(int iShape=0; iShape<Get_Shapes()->Get_Count() && s.Get_Count()<maxClasses; iShape++)
868 {
869 s += Get_Shapes()->Get_Shape(iShape)->asString(Field);
870 }
871
872 Colors.Set_Count(s.Get_Count());
873
874 for(int iClass=0; iClass<s.Get_Count(); iClass++)
875 {
876 CSG_String Value = s.Get_Value(iClass);
877
878 CSG_Table_Record *pClass = Classes.Add_Record();
879
880 pClass->Set_Value(0, Colors[iClass]); // Color
881 pClass->Set_Value(1, Value ); // Name
882 pClass->Set_Value(2, Value ); // Description
883 pClass->Set_Value(3, Value ); // Minimum
884 pClass->Set_Value(4, Value ); // Maximum
885 }
886 }
887 break;
888
889 //-----------------------------------------------------
890 case 1: // equal intervals
891 {
892 double Minimum, Maximum, Interval;
893
894 Interval = Get_Shapes()->Get_Range (Field) / (double)Colors.Get_Count();
895 Minimum = Get_Shapes()->Get_Minimum(Field);
896
897 Classes.Set_Field_Type(LUT_MIN, SG_DATATYPE_Double);
898 Classes.Set_Field_Type(LUT_MAX, SG_DATATYPE_Double);
899
900 for(int iClass=0; iClass<Colors.Get_Count(); iClass++, Minimum+=Interval)
901 {
902 Maximum = iClass < Colors.Get_Count() - 1 ? Minimum + Interval : Get_Shapes()->Get_Maximum(Field) + 1.;
903
904 CSG_String Name = SG_Get_String(Minimum, -2)
905 + " - " + SG_Get_String(Maximum, -2);
906
907 CSG_Table_Record *pClass = Classes.Add_Record();
908
909 pClass->Set_Value(0, Colors[iClass]); // Color
910 pClass->Set_Value(1, Name ); // Name
911 pClass->Set_Value(2, Name ); // Description
912 pClass->Set_Value(3, Minimum ); // Minimum
913 pClass->Set_Value(4, Maximum ); // Maximum
914 }
915 }
916 break;
917
918 //-----------------------------------------------------
919 case 2: // quantiles
920 {
921 TSG_Table_Index_Order old_Order = Get_Shapes()->Get_Index_Order(0);
922 int old_Field = Get_Shapes()->Get_Index_Field(0);
923
924 Get_Shapes()->Set_Index(Field, TABLE_INDEX_Ascending);
925
926 Classes.Set_Field_Type(LUT_MIN, SG_DATATYPE_Double);
927 Classes.Set_Field_Type(LUT_MAX, SG_DATATYPE_Double);
928
929 if( Get_Shapes()->Get_Count() < Colors.Get_Count() )
930 {
931 Colors.Set_Count(Get_Shapes()->Get_Count());
932 }
933
934 double Minimum, Maximum, Count, iRecord;
935
936 Maximum = Get_Shapes()->Get_Minimum(Field);
937 iRecord = Count = Get_Shapes()->Get_Count() / (double)Colors.Get_Count();
938
939 for(int iClass=0; iClass<Colors.Get_Count(); iClass++, iRecord+=Count)
940 {
941 Minimum = Maximum;
942 Maximum = iRecord < Get_Shapes()->Get_Count() ? Get_Shapes()->Get_Record_byIndex((int)iRecord)->asDouble(Field) : Get_Shapes()->Get_Maximum(Field) + 1.;
943
944 CSG_String Name = SG_Get_String(Minimum, -2)
945 + " - " + SG_Get_String(Maximum, -2);
946
947 CSG_Table_Record *pClass = Classes.Add_Record();
948
949 pClass->Set_Value(0, Colors[iClass]); // Color
950 pClass->Set_Value(1, Name ); // Name
951 pClass->Set_Value(2, Name ); // Description
952 pClass->Set_Value(3, Minimum ); // Minimum
953 pClass->Set_Value(4, Maximum ); // Maximum
954 }
955
956 Get_Shapes()->Set_Index(old_Field, old_Order);
957 }
958 break;
959
960 //-----------------------------------------------------
961 case 3: // natural breaks
962 {
963 CSG_Natural_Breaks Breaks(Get_Shapes(), Field, Colors.Get_Count(), Get_Shapes()->Get_Count() > 4096 ? 256 : 0);
964
965 if( Breaks.Get_Count() <= Colors.Get_Count() ) return;
966
967 Classes.Set_Field_Type(LUT_MIN, SG_DATATYPE_Double);
968 Classes.Set_Field_Type(LUT_MAX, SG_DATATYPE_Double);
969
970 for(int iClass=0; iClass<Colors.Get_Count(); iClass++)
971 {
972 CSG_Table_Record *pClass = Classes.Add_Record();
973
974 double Minimum = Breaks[iClass ];
975 double Maximum = Breaks[iClass + 1];
976
977 CSG_String Name = SG_Get_String(Minimum, -2)
978 + " - " + SG_Get_String(Maximum, -2);
979
980 pClass->Set_Value(0, Colors[iClass]); // Color
981 pClass->Set_Value(1, Name ); // Name
982 pClass->Set_Value(2, Name ); // Description
983 pClass->Set_Value(3, Minimum ); // Minimum
984 pClass->Set_Value(4, Maximum ); // Maximum
985 }
986 }
987 break;
988 }
989
990 //-----------------------------------------------------
991 if( Classes.Get_Count() > 0 )
992 {
993 m_Parameters("LUT")->asTable()->Assign(&Classes);
994 m_Parameters("LUT")->asTable()->Get_MetaData().Add_Child("SAGA_GUI_LUT_TYPE", m_pObject->Get_ObjectType());
995
996 m_Parameters("COLORS_TYPE")->Set_Value(CLASSIFY_LUT); // Lookup Table
997 m_Parameters("LUT_ATTRIB" )->Set_Value(Field);
998
999 Parameters_Changed();
1000 }
1001 }
1002
1003 //---------------------------------------------------------
_LUT_Import(void)1004 void CWKSP_Shapes::_LUT_Import(void)
1005 {
1006 wxString File, Filter;
1007
1008 Filter.Printf("%s (*.qml)|*.qml|%s|*.*", _TL("QGIS Layer Style File"), _TL("All Files"));
1009
1010 if( DLG_Open(File, _TL("Import Classification"), SG_T("QGIS Layer Style File (*.qml)|*.qml|All Files|*.*|")) )
1011 {
1012 CSG_Table Classes;
1013 CSG_String Attribute;
1014
1015 if( QGIS_Styles_Import(&File, Classes, Attribute) )
1016 {
1017 m_Parameters.Set_Parameter("LUT_ATTRIB", Attribute);
1018
1019 m_Parameters("LUT")->asTable()->Assign(&Classes);
1020 m_Parameters("LUT")->asTable()->Get_MetaData().Add_Child("SAGA_GUI_LUT_TYPE", m_pObject->Get_ObjectType());
1021
1022 m_Parameters("COLORS_TYPE")->Set_Value(CLASSIFY_LUT); // Lookup Table
1023
1024 Parameters_Changed();
1025 }
1026 }
1027 }
1028
1029
1030 ///////////////////////////////////////////////////////////
1031 // //
1032 ///////////////////////////////////////////////////////////
1033
1034 //---------------------------------------------------------
Get_Value(CSG_Point ptWorld,double Epsilon)1035 wxString CWKSP_Shapes::Get_Value(CSG_Point ptWorld, double Epsilon)
1036 {
1037 CSG_Shape *pShape = Get_Shapes()->Get_Shape(ptWorld, Epsilon);
1038
1039 if( pShape == NULL )
1040 {
1041 return( _TL("") );
1042 }
1043
1044 if( m_fValue < 0 )
1045 {
1046 return( wxString::Format("%s: %d", _TL("Index"), pShape->Get_Index() + 1) );
1047 }
1048
1049 if( m_pClassify->Get_Mode() == CLASSIFY_LUT )
1050 {
1051 return( m_pClassify->Get_Class_Name_byValue(pShape->asString(m_fValue)) );
1052 }
1053
1054 if( !pShape->is_NoData(m_fValue) )
1055 {
1056 if( m_fNormal < 0 )
1057 {
1058 return( pShape->asString(m_fValue) );
1059 }
1060
1061 if( !pShape->is_NoData(m_fNormal) && pShape->asDouble(m_fNormal) != 0. )
1062 {
1063 return( wxString::Format("%f", m_dNormal * pShape->asDouble(m_fValue) / pShape->asDouble(m_fNormal)) );
1064 }
1065 }
1066
1067 return( _TL("") );
1068 }
1069
1070
1071 ///////////////////////////////////////////////////////////
1072 // //
1073 ///////////////////////////////////////////////////////////
1074
1075 //---------------------------------------------------------
Get_Value_Minimum(void)1076 double CWKSP_Shapes::Get_Value_Minimum(void) { return( m_Metrics.Get_Minimum() ); }
Get_Value_Maximum(void)1077 double CWKSP_Shapes::Get_Value_Maximum(void) { return( m_Metrics.Get_Maximum() ); }
Get_Value_Range(void)1078 double CWKSP_Shapes::Get_Value_Range (void) { return( m_Metrics.Get_Range () ); }
Get_Value_Mean(void)1079 double CWKSP_Shapes::Get_Value_Mean (void) { return( m_Metrics.Get_Mean () ); }
Get_Value_StdDev(void)1080 double CWKSP_Shapes::Get_Value_StdDev (void) { return( m_Metrics.Get_StdDev () ); }
1081
1082
1083 ///////////////////////////////////////////////////////////
1084 // //
1085 ///////////////////////////////////////////////////////////
1086
1087 //---------------------------------------------------------
Get_Name_Attribute(void)1088 wxString CWKSP_Shapes::Get_Name_Attribute(void)
1089 {
1090 wxString s;
1091
1092 if( m_fValue >= 0 && m_pClassify->Get_Mode() != CLASSIFY_SINGLE )
1093 {
1094 s = Get_Shapes()->Get_Field_Name(m_fValue);
1095
1096 if( m_fNormal >= 0
1097 && (m_pClassify->Get_Mode() == CLASSIFY_DISCRETE
1098 || m_pClassify->Get_Mode() == CLASSIFY_GRADUATED) )
1099 {
1100 s += " / "; s += Get_Shapes()->Get_Field_Name(m_fNormal);
1101 }
1102 }
1103
1104 return( s );
1105 }
1106
1107
1108 ///////////////////////////////////////////////////////////
1109 // //
1110 ///////////////////////////////////////////////////////////
1111
1112 //---------------------------------------------------------
On_Draw(CWKSP_Map_DC & dc_Map,int Flags)1113 void CWKSP_Shapes::On_Draw(CWKSP_Map_DC &dc_Map, int Flags)
1114 {
1115 //-----------------------------------------------------
1116 if( Get_Extent().Intersects(dc_Map.m_rWorld) == INTERSECTION_None )
1117 {
1118 if( m_Edit_pShape )
1119 {
1120 Edit_Shape_Draw(dc_Map);
1121 }
1122
1123 return;
1124 }
1125
1126 //-----------------------------------------------------
1127 if( (Flags & LAYER_DRAW_FLAG_THUMBNAIL) != 0 )
1128 {
1129 Draw_Initialize(dc_Map, Flags);
1130
1131 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1132 {
1133 _Draw_Shape(dc_Map, Get_Shapes()->Get_Shape(iShape));
1134 }
1135
1136 return;
1137 }
1138
1139 //-----------------------------------------------------
1140 double Transparency = m_Parameters("DISPLAY_TRANSPARENCY")->asDouble() / 100.;
1141
1142 CWKSP_Map_DC *pDC = Transparency > 0. ? new CWKSP_Map_DC(dc_Map.m_rWorld, dc_Map.m_rDC, dc_Map.m_Scale, SG_GET_RGB(254, 255, 255)) : NULL;
1143 CWKSP_Map_DC &dc = pDC ? *pDC : dc_Map;
1144
1145 m_Sel_Color = Get_Color_asWX(m_Parameters("SEL_COLOR" )->asInt());
1146 m_Edit_Color = Get_Color_asWX(m_Parameters("EDIT_COLOR")->asInt());
1147 m_Edit_bGleam = m_Parameters("EDIT_GLEAM")->asBool();
1148
1149 Draw_Initialize(dc, Flags);
1150
1151 //-----------------------------------------------------
1152 if( (Flags & LAYER_DRAW_FLAG_NOEDITS) != 0 || !(m_Edit_pShape || Get_Shapes()->Get_Selection_Count()) )
1153 {
1154 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1155 {
1156 _Draw_Shape(dc, Get_Shapes()->Get_Shape(iShape));
1157 }
1158
1159 if( _Chart_is_Valid() )
1160 {
1161 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1162 {
1163 _Draw_Chart(dc, Get_Shapes()->Get_Shape(iShape));
1164 }
1165 }
1166 }
1167 else // selection and/or editing
1168 {
1169 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1170 {
1171 if( !Get_Shapes()->Get_Shape(iShape)->is_Selected() )
1172 {
1173 _Draw_Shape(dc, Get_Shapes()->Get_Shape(iShape));
1174 }
1175 }
1176
1177 for(int iShape=0; iShape<(int)Get_Shapes()->Get_Selection_Count(); iShape++)
1178 {
1179 if( iShape != m_Edit_Index )
1180 {
1181 _Draw_Shape(dc, Get_Shapes()->Get_Selection(iShape), 2);
1182 }
1183 }
1184
1185 //-------------------------------------------------
1186 if( !m_Edit_pShape )
1187 {
1188 _Draw_Shape(dc, Get_Shapes()->Get_Selection(m_Edit_Index), 1);
1189 }
1190 else
1191 {
1192 Edit_Shape_Draw(dc);
1193 }
1194
1195 if( m_Edit_Mode == EDIT_SHAPE_MODE_Split )
1196 {
1197 CSG_Shape *pSplit = m_Edit_Shapes.Get_Shape(1);
1198
1199 if( pSplit && pSplit->Get_Point_Count() > 1 )
1200 {
1201 for(int i=0; i<=1; i++)
1202 {
1203 dc_Map.dc.SetPen(wxPen(i == 0 ? *wxWHITE : *wxBLACK, i == 0 ? 3 : 1));
1204
1205 TSG_Point_Int B, A = dc_Map.World2DC(pSplit->Get_Point(0));
1206
1207 for(int iPoint=1; iPoint<pSplit->Get_Point_Count(); iPoint++)
1208 {
1209 B = A; A = dc_Map.World2DC(pSplit->Get_Point(iPoint));
1210
1211 dc_Map.dc.DrawLine(A.x, A.y, B.x, B.y);
1212 }
1213 }
1214 }
1215 }
1216 }
1217
1218 //-----------------------------------------------------
1219 if( (Flags & LAYER_DRAW_FLAG_NOLABELS) == 0 && m_fLabel >= 0 ) // Labels
1220 {
1221 int iSize = m_Parameters("LABEL_ATTRIB_SIZE_BY" )->asInt();
1222 double dSize = m_Parameters("LABEL_ATTRIB_SIZE_TYPE")->asInt() == 1 ?
1223 dc.m_World2DC * m_Parameters("LABEL_ATTRIB_SIZE")->asDouble() : 1.;
1224
1225 dc.dc.SetFont(Get_Font (m_Parameters("LABEL_ATTRIB_FONT")));
1226 dc.dc.SetTextForeground(m_Parameters("LABEL_ATTRIB_FONT")->asColor());
1227
1228 if( iSize >= 0 && iSize < Get_Shapes()->Get_Field_Count() ) // size by attribute
1229 {
1230 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1231 {
1232 int Size = (int)(0.5 + dSize * Get_Shapes()->Get_Shape(iShape)->asDouble(iSize));
1233
1234 if( Size > 0 )
1235 {
1236 _Draw_Label(dc, Get_Shapes()->Get_Shape(iShape), Size);
1237 }
1238 }
1239 }
1240 else // one size fits all
1241 {
1242 int Size = m_Parameters("LABEL_ATTRIB_SIZE_TYPE")->asInt() == 1 ? (int)(0.5 + dSize) : dc.dc.GetFont().GetPointSize();
1243
1244 if( Size > 0 )
1245 {
1246 for(int iShape=0; iShape<Get_Shapes()->Get_Count(); iShape++)
1247 {
1248 _Draw_Label(dc, Get_Shapes()->Get_Shape(iShape), Size);
1249 }
1250 }
1251 }
1252 }
1253
1254 //-----------------------------------------------------
1255 if( pDC ) // Transparency ?
1256 {
1257 dc_Map.Draw_DC(dc, Transparency);
1258
1259 delete(pDC);
1260 }
1261 }
1262
1263 //---------------------------------------------------------
_Draw_Shape(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape,int Selection)1264 void CWKSP_Shapes::_Draw_Shape(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape, int Selection)
1265 {
1266 if( pShape && dc_Map.m_rWorld.Intersects(pShape->Get_Extent()) != INTERSECTION_None )
1267 {
1268 Draw_Shape(dc_Map, pShape, Selection);
1269
1270 if( m_bVertices > 0 )
1271 {
1272 wxPen oldPen (dc_Map.dc.GetPen ()); dc_Map.dc.SetPen (*wxBLACK_PEN );
1273 wxBrush oldBrush(dc_Map.dc.GetBrush()); dc_Map.dc.SetBrush(*wxWHITE_BRUSH);
1274
1275 for(int iPart=0; iPart<pShape->Get_Part_Count(); iPart++)
1276 {
1277 for(int iPoint=0; iPoint<pShape->Get_Point_Count(iPart); iPoint++)
1278 {
1279 TSG_Point_Int A = dc_Map.World2DC(pShape->Get_Point(iPoint, iPart));
1280
1281 dc_Map.dc.DrawCircle(A.x, A.y, 2);
1282
1283 if( m_bVertices == 2 )
1284 {
1285 Draw_Text(dc_Map.dc, TEXTALIGN_TOPLEFT, A.x, A.y, wxString::Format("%d", iPoint + 1));
1286 }
1287 }
1288 }
1289
1290 dc_Map.dc.SetPen (oldPen );
1291 dc_Map.dc.SetBrush(oldBrush);
1292 }
1293 }
1294 }
1295
1296 //---------------------------------------------------------
_Draw_Label(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape,int PointSize)1297 void CWKSP_Shapes::_Draw_Label(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape, int PointSize)
1298 {
1299 if( pShape && dc_Map.m_rWorld.Intersects(pShape->Get_Extent()) != INTERSECTION_None )
1300 {
1301 wxString Label(pShape->asString(m_fLabel, m_Label_Prec)); Label.Trim(true).Trim(false);
1302
1303 if( !Label.IsEmpty() )
1304 {
1305 if( PointSize > 0 && PointSize != dc_Map.dc.GetFont().GetPointSize() )
1306 {
1307 wxFont Font(dc_Map.dc.GetFont());
1308
1309 Font.SetPointSize(PointSize);
1310
1311 dc_Map.dc.SetFont(Font);
1312 }
1313
1314 Draw_Label(dc_Map, pShape, Label);
1315 }
1316 }
1317 }
1318
1319
1320 ///////////////////////////////////////////////////////////
1321 // //
1322 ///////////////////////////////////////////////////////////
1323
1324 //---------------------------------------------------------
AttributeList_Set(CSG_Parameter * pFields,bool bAddNoField)1325 void CWKSP_Shapes::AttributeList_Set(CSG_Parameter *pFields, bool bAddNoField)
1326 {
1327 if( pFields && pFields->Get_Type() == PARAMETER_TYPE_Choice )
1328 {
1329 CSG_String Items;
1330
1331 for(int i=0; i<Get_Shapes()->Get_Field_Count(); i++)
1332 {
1333 Items += CSG_String(Get_Shapes()->Get_Field_Name(i)) + "|";
1334 }
1335
1336 if( bAddNoField || Get_Shapes()->Get_Field_Count() == 0 )
1337 {
1338 Items += CSG_String(_TL("<none>")) + "|";
1339 }
1340
1341 int iChoice = pFields->asInt ();
1342 CSG_String sChoice = pFields->asString();
1343
1344 pFields->asChoice()->Set_Items(Items);
1345
1346 if( bAddNoField && (iChoice < 0 || iChoice >= pFields->asChoice()->Get_Count() || sChoice.Cmp(pFields->asChoice()->Get_Item(iChoice))) )
1347 {
1348 pFields->Set_Value(Get_Shapes()->Get_Field_Count());
1349 }
1350 }
1351 }
1352
1353
1354 ///////////////////////////////////////////////////////////
1355 // //
1356 ///////////////////////////////////////////////////////////
1357
1358 //---------------------------------------------------------
BrushList_Add(const CSG_String & ParentID,const CSG_String & Identifier,const CSG_String & Name,const CSG_String & Description)1359 CSG_Parameter * CWKSP_Shapes::BrushList_Add(const CSG_String &ParentID, const CSG_String &Identifier, const CSG_String &Name, const CSG_String &Description)
1360 {
1361 return( m_Parameters.Add_Choice(ParentID, Identifier, Name, Description,
1362 CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|",
1363 _TL("Opaque" ),
1364 _TL("Transparent" ),
1365 _TL("Backward Diagonal"),
1366 _TL("Cross Diagonal" ),
1367 _TL("Forward Diagonal" ),
1368 _TL("Cross" ),
1369 _TL("Horizontal" ),
1370 _TL("Vertical" )
1371 ), 0)
1372 );
1373 }
1374
1375 //---------------------------------------------------------
BrushList_Get_Style(const CSG_String & Identifier)1376 wxBrushStyle CWKSP_Shapes::BrushList_Get_Style(const CSG_String &Identifier)
1377 {
1378 switch( m_Parameters(Identifier)->asInt() )
1379 {
1380 default: return( wxBRUSHSTYLE_SOLID );
1381 case 1: return( wxBRUSHSTYLE_TRANSPARENT );
1382 case 2: return( wxBRUSHSTYLE_BDIAGONAL_HATCH );
1383 case 3: return( wxBRUSHSTYLE_CROSSDIAG_HATCH );
1384 case 4: return( wxBRUSHSTYLE_FDIAGONAL_HATCH );
1385 case 5: return( wxBRUSHSTYLE_CROSS_HATCH );
1386 case 6: return( wxBRUSHSTYLE_HORIZONTAL_HATCH);
1387 case 7: return( wxBRUSHSTYLE_VERTICAL_HATCH );
1388 }
1389 }
1390
1391 //---------------------------------------------------------
PenList_Add(const CSG_String & ParentID,const CSG_String & Identifier,const CSG_String & Name,const CSG_String & Description)1392 CSG_Parameter * CWKSP_Shapes::PenList_Add(const CSG_String &ParentID, const CSG_String &Identifier, const CSG_String &Name, const CSG_String &Description)
1393 {
1394 return( m_Parameters.Add_Choice(ParentID, Identifier, Name, Description,
1395 CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|",
1396 _TL("Solid style"),
1397 _TL("Dotted style"),
1398 _TL("Long dashed style"),
1399 _TL("Short dashed style"),
1400 _TL("Dot and dash style"),
1401 _TL("Backward diagonal hatch"),
1402 _TL("Cross-diagonal hatch"),
1403 _TL("Forward diagonal hatch"),
1404 _TL("Cross hatch"),
1405 _TL("Horizontal hatch"),
1406 _TL("Vertical hatch")
1407 // _TL("Use the stipple bitmap")
1408 // _TL("Use the user dashes")
1409 // _TL("No pen is used")
1410 ), 0)
1411 );
1412 }
1413
1414 //---------------------------------------------------------
PenList_Get_Style(const CSG_String & Identifier)1415 int CWKSP_Shapes::PenList_Get_Style(const CSG_String &Identifier)
1416 {
1417 switch( m_Parameters(Identifier)->asInt() )
1418 {
1419 default: return( wxPENSTYLE_SOLID ); // Solid style.
1420 case 1: return( wxPENSTYLE_DOT ); // Dotted style.
1421 case 2: return( wxPENSTYLE_LONG_DASH ); // Long dashed style.
1422 case 3: return( wxPENSTYLE_SHORT_DASH ); // Short dashed style.
1423 case 4: return( wxPENSTYLE_DOT_DASH ); // Dot and dash style.
1424 case 5: return( wxPENSTYLE_BDIAGONAL_HATCH ); // Backward diagonal hatch.
1425 case 6: return( wxPENSTYLE_CROSSDIAG_HATCH ); // Cross-diagonal hatch.
1426 case 7: return( wxPENSTYLE_FDIAGONAL_HATCH ); // Forward diagonal hatch.
1427 case 8: return( wxPENSTYLE_CROSS_HATCH ); // Cross hatch.
1428 case 9: return( wxPENSTYLE_HORIZONTAL_HATCH ); // Horizontal hatch.
1429 case 10: return( wxPENSTYLE_VERTICAL_HATCH ); // Vertical hatch.
1430 // case 11: return( wxPENSTYLE_STIPPLE ); // Use the stipple bitmap.
1431 // case 12: return( wxPENSTYLE_USER_DASH ); // Use the user dashes: see wxPen::SetDashes.
1432 // case 13: return( wxPENSTYLE_TRANSPARENT ); // No pen is used.
1433 }
1434 }
1435
1436
1437 ///////////////////////////////////////////////////////////
1438 // //
1439 ///////////////////////////////////////////////////////////
1440
1441 //---------------------------------------------------------
Get_Class_Color(CSG_Shape * pShape,int & Color)1442 bool CWKSP_Shapes::Get_Class_Color(CSG_Shape *pShape, int &Color)
1443 {
1444 //-----------------------------------------------------
1445 if( m_fValue >= 0 )
1446 {
1447 if( m_pClassify->Get_Mode() == CLASSIFY_LUT )
1448 {
1449 if( !SG_Data_Type_is_Numeric(Get_Shapes()->Get_Field_Type(m_fValue)) )
1450 {
1451 return( m_pClassify->Get_Class_Color_byValue(pShape->asString(m_fValue), Color) );
1452 }
1453 else
1454 {
1455 return( m_pClassify->Get_Class_Color_byValue(pShape->asDouble(m_fValue), Color) );
1456 }
1457 }
1458
1459 //-------------------------------------------------
1460 if( !pShape->is_NoData(m_fValue) )
1461 {
1462 if( m_fNormal < 0 ) // don't normalize
1463 {
1464 return( m_pClassify->Get_Class_Color_byValue(pShape->asDouble(m_fValue), Color) );
1465 }
1466
1467 if( !pShape->is_NoData(m_fNormal) && pShape->asDouble(m_fNormal) != 0. )
1468 {
1469 return( m_pClassify->Get_Class_Color_byValue(m_dNormal * pShape->asDouble(m_fValue) / pShape->asDouble(m_fNormal), Color) );
1470 }
1471 }
1472 }
1473
1474 //-----------------------------------------------------
1475 Color = m_pClassify->Get_Unique_Color();
1476
1477 return( m_pClassify->Get_Mode() == CLASSIFY_SINGLE );
1478 }
1479
1480
1481 ///////////////////////////////////////////////////////////
1482 // //
1483 ///////////////////////////////////////////////////////////
1484
1485 //---------------------------------------------------------
_Chart_Set_Options(void)1486 bool CWKSP_Shapes::_Chart_Set_Options(void)
1487 {
1488 CSG_Parameters *pChart = m_Parameters("DISPLAY_CHART")->asParameters();
1489
1490 pChart->Del_Parameters();
1491 m_Chart.Clear();
1492
1493 if( 1 )
1494 {
1495 int i, n;
1496
1497 for(i=0, n=0; i<Get_Shapes()->Get_Field_Count(); i++)
1498 {
1499 if( Get_Shapes()->Get_Field_Type(i) != SG_DATATYPE_String )
1500 {
1501 n++;
1502 }
1503 }
1504
1505 if( n > 0 )
1506 {
1507 pChart->Add_Choice("",
1508 "TYPE" , _TL("Chart Type"),
1509 _TL(""),
1510 CSG_String::Format("%s|%s|%s|%s|",
1511 _TL("bar"),
1512 _TL("bar (not outlined)"),
1513 _TL("pie"),
1514 _TL("pie (not outlined)")
1515 ), 0
1516 );
1517
1518 pChart->Add_Choice("",
1519 "SIZE_FIELD" , _TL("Attribute (Size)"),
1520 _TL(""),
1521 CSG_String::Format("%s|", _TL("<not set>")), 0
1522 );
1523
1524 pChart->Add_Choice("",
1525 "SIZE_TYPE" , _TL("Size relates to..."),
1526 _TL(""),
1527 CSG_String::Format("%s|%s|",
1528 _TL("Screen"),
1529 _TL("Map Units")
1530 ), 0
1531 );
1532
1533 pChart->Add_Double("",
1534 "SIZE_DEFAULT" , _TL("Default Size"),
1535 _TL(""),
1536 15., 0., true
1537 );
1538
1539 pChart->Add_Range("",
1540 "SIZE_RANGE" , _TL("Size Range"),
1541 _TL(""),
1542 5, 25, 0, true
1543 );
1544
1545 pChart->Add_Node("", "FIELDS", _TL("Fields"), _TL(""));
1546
1547 CSG_String Fields, Field;
1548 CSG_Colors Colors(n);
1549
1550 for(i=0, n=0; i<Get_Shapes()->Get_Field_Count(); i++)
1551 {
1552 if( Get_Shapes()->Get_Field_Type(i) != SG_DATATYPE_String )
1553 {
1554 Fields += CSG_String::Format("%s|", Get_Shapes()->Get_Field_Name(i));
1555
1556 Field.Printf("FIELD_%d", i);
1557
1558 pChart->Add_Bool("FIELDS", Field, Get_Shapes()->Get_Field_Name(i), _TL(""), false);
1559 pChart->Add_Color(Field, CSG_String::Format("COLOR_%d", i), SG_T(""), _TL(""), Colors.Get_Color(n++));
1560 }
1561 }
1562
1563 Fields += CSG_String::Format("%s|", _TL("<none>"));
1564
1565 (*pChart)("SIZE_FIELD")->asChoice()->Set_Items(Fields);
1566 (*pChart)("SIZE_FIELD")->Set_Value(n);
1567
1568 return( true );
1569 }
1570 }
1571
1572 return( false );
1573 }
1574
1575 //---------------------------------------------------------
_Chart_Get_Options(void)1576 bool CWKSP_Shapes::_Chart_Get_Options(void)
1577 {
1578 m_Chart.Clear();
1579 m_Chart_sField = -1;
1580
1581 CSG_Parameters *pChart = m_Parameters("DISPLAY_CHART")->asParameters();
1582
1583 if( (*pChart)("FIELDS") )
1584 {
1585 for(int i=0, n=0; i<Get_Shapes()->Get_Field_Count(); i++)
1586 {
1587 CSG_Parameter *p = (*pChart)(CSG_String::Format("FIELD_%d", i));
1588
1589 if( p )
1590 {
1591 if( (*pChart)("SIZE_FIELD")->asInt() == n++ )
1592 m_Chart_sField = i;
1593
1594 if( p->asBool() && (p = (*pChart)(CSG_String::Format("COLOR_%d", i))) != NULL )
1595 m_Chart.Add(i, p->asColor());
1596 }
1597 }
1598
1599 m_Chart_Type = (*pChart)("TYPE" )->asInt();
1600 m_Chart_sType = (*pChart)("SIZE_TYPE" )->asInt();
1601 m_Chart_sSize = m_Chart_sField < 0
1602 ? (*pChart)("SIZE_DEFAULT")->asDouble()
1603 : (*pChart)("SIZE_RANGE" )->asRange()->Get_Min();
1604 m_Chart_sRange = (*pChart)("SIZE_RANGE" )->asRange()->Get_Max() - m_Chart_sSize;
1605
1606 return( true );
1607 }
1608
1609 return( false );
1610 }
1611
1612 //---------------------------------------------------------
_Draw_Chart(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape)1613 void CWKSP_Shapes::_Draw_Chart(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape)
1614 {
1615 if( dc_Map.m_rWorld.Intersects(pShape->Get_Extent()) != INTERSECTION_None )
1616 {
1617 int s;
1618 double dSize = m_Chart_sSize;
1619 TSG_Point_Int p;
1620
1621 if( m_Chart_sField >= 0 )
1622 {
1623 double range = Get_Shapes()->Get_Range(m_Chart_sField);
1624
1625 if( range > 0. )
1626 {
1627 dSize += m_Chart_sRange * ((pShape->asDouble(m_Chart_sField) - Get_Shapes()->Get_Minimum(m_Chart_sField)) / range);
1628 }
1629 }
1630
1631 s = (int)(dSize * (m_Chart_sType == 1 ? dc_Map.m_World2DC : dc_Map.m_Scale));
1632
1633 switch( pShape->Get_Type() )
1634 {
1635 default: p = dc_Map.World2DC(pShape->Get_Extent().Get_Center()); break;
1636 case SHAPE_TYPE_Polygon: p = dc_Map.World2DC(((CSG_Shape_Polygon *)pShape)->Get_Centroid()); break;
1637 }
1638
1639 dc_Map.dc.SetPen(*wxBLACK_PEN);
1640
1641 switch( m_Chart_Type )
1642 {
1643 case 0: _Draw_Chart_Bar(dc_Map, pShape, true, p.x, p.y, (int)(0.8 * s), s); break; // bar outlined
1644 case 1: _Draw_Chart_Bar(dc_Map, pShape, false, p.x, p.y, (int)(0.8 * s), s); break; // bar
1645 case 2: _Draw_Chart_Pie(dc_Map, pShape, true, p.x, p.y, (int)(1.0 * s)); break; // pie outlined
1646 case 3: _Draw_Chart_Pie(dc_Map, pShape, false, p.x, p.y, (int)(1.0 * s)); break; // pie
1647 }
1648 }
1649 }
1650
1651 //---------------------------------------------------------
_Draw_Chart_Pie(CWKSP_Map_DC & dc_Map,CSG_Table_Record * pRecord,bool bOutline,int x,int y,int size)1652 void CWKSP_Shapes::_Draw_Chart_Pie(CWKSP_Map_DC &dc_Map, CSG_Table_Record *pRecord, bool bOutline, int x, int y, int size)
1653 {
1654 int i, ix, iy, jx, jy;
1655 double d, sum;
1656
1657 for(i=0, sum=0.; i<m_Chart.Get_Count(); i++)
1658 {
1659 sum += fabs(pRecord->asDouble(m_Chart[i].x));
1660 }
1661
1662 if( sum > 0. )
1663 {
1664 sum = M_PI_360 / sum;
1665
1666 for(i=0, jx=x, jy=y-size, d=0.; i<m_Chart.Get_Count(); i++)
1667 {
1668 if( !bOutline )
1669 dc_Map.dc.SetPen (wxPen (Get_Color_asWX(m_Chart[i].y)));
1670 dc_Map.dc.SetBrush (wxBrush(Get_Color_asWX(m_Chart[i].y)));
1671
1672 d += sum * fabs(pRecord->asDouble(m_Chart[i].x));
1673
1674 ix = jx;
1675 iy = jy;
1676 jx = x - (int)(size * sin(-d));
1677 jy = y - (int)(size * cos(-d));
1678
1679 dc_Map.dc.DrawArc(jx, jy, ix, iy, x, y);
1680 }
1681 }
1682 }
1683
1684 //---------------------------------------------------------
_Draw_Chart_Bar(CWKSP_Map_DC & dc_Map,CSG_Table_Record * pRecord,bool bOutline,int x,int y,int sx,int sy)1685 void CWKSP_Shapes::_Draw_Chart_Bar(CWKSP_Map_DC &dc_Map, CSG_Table_Record *pRecord, bool bOutline, int x, int y, int sx, int sy)
1686 {
1687 int i;
1688 double d, dx, dy, max, ix;
1689
1690 y += sy / 2;
1691
1692 for(i=1, max=fabs(pRecord->asDouble(m_Chart[0].x)); i<m_Chart.Get_Count(); i++)
1693 {
1694 if( (d = fabs(pRecord->asDouble(m_Chart[i].x))) > max )
1695 max = d;
1696 }
1697
1698 if( max != 0. )
1699 {
1700 max = sy / max;
1701 dx = sx / (double)m_Chart.Get_Count();
1702
1703 for(i=0, ix=x-sx/2.; i<m_Chart.Get_Count(); i++, ix+=dx)
1704 {
1705 if( !bOutline )
1706 dc_Map.dc.SetPen (wxPen (Get_Color_asWX(m_Chart[i].y)));
1707 dc_Map.dc.SetBrush (wxBrush(Get_Color_asWX(m_Chart[i].y)));
1708
1709 dy = -pRecord->asDouble(m_Chart[i].x) * max;
1710
1711 dc_Map.dc.DrawRectangle((int)ix, y, (int)dx, (int)dy);
1712 }
1713
1714 if( !bOutline )
1715 {
1716 dc_Map.dc.SetPen(*wxBLACK_PEN);
1717 dc_Map.dc.DrawLine(x - sx / 2, y, x + sx / 2, y);
1718 }
1719 }
1720 }
1721
1722
1723 ///////////////////////////////////////////////////////////
1724 // //
1725 // //
1726 // //
1727 ///////////////////////////////////////////////////////////
1728
1729 //---------------------------------------------------------
1730