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_Line.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 //                Germany                                //
43 //                                                       //
44 //    e-mail:     oconrad@saga-gis.org                   //
45 //                                                       //
46 ///////////////////////////////////////////////////////////
47 
48 //---------------------------------------------------------
49 #include <saga_gdi/sgdi_helper.h>
50 
51 #include "wksp_layer_classify.h"
52 
53 #include "wksp_shapes_line.h"
54 
55 
56 ///////////////////////////////////////////////////////////
57 //														 //
58 //														 //
59 //														 //
60 ///////////////////////////////////////////////////////////
61 
62 //---------------------------------------------------------
CWKSP_Shapes_Line(CSG_Shapes * pShapes)63 CWKSP_Shapes_Line::CWKSP_Shapes_Line(CSG_Shapes *pShapes)
64 	: CWKSP_Shapes(pShapes)
65 {
66 	On_Create_Parameters();
67 
68 	DataObject_Changed();
69 }
70 
71 
72 ///////////////////////////////////////////////////////////
73 //														 //
74 ///////////////////////////////////////////////////////////
75 
76 //---------------------------------------------------------
On_Create_Parameters(void)77 void CWKSP_Shapes_Line::On_Create_Parameters(void)
78 {
79 	CWKSP_Shapes::On_Create_Parameters();
80 
81 	//-----------------------------------------------------
82 	// Display...
83 
84 	m_Parameters.Add_Choice("NODE_DISPLAY",
85 		"DISPLAY_POINTS"	, _TL("Show Vertices"),
86 		_TL(""),
87 		CSG_String::Format("%s|%s|%s",
88 			_TL("no"),
89 			_TL("yes"),
90 			_TL("with label")
91 		), 0
92 	);
93 
94 	PenList_Add("NODE_DISPLAY",
95 		"LINE_STYLE"		, _TL("Line Style"),
96 		_TL("")
97 	);
98 
99 
100 	//-----------------------------------------------------
101 	// Size...
102 
103 	m_Parameters.Add_Choice("NODE_SIZE",
104 		"SIZE_TYPE"			, _TL("Size relates to..."),
105 		_TL(""),
106 		CSG_String::Format("%s|%s",
107 			_TL("Screen"),
108 			_TL("Map Units")
109 		), 0
110 	);
111 
112 	m_Parameters.Add_Choice("NODE_SIZE",
113 		"SIZE_ATTRIB"		, _TL("Attribute"),
114 		_TL(""),
115 		_TL("<default>")
116 	);
117 
118 	m_Parameters.Add_Range("SIZE_ATTRIB",
119 		"SIZE_RANGE"		, _TL("Size Range"),
120 		_TL(""),
121 		0, 10, 0, true
122 	);
123 
124 	m_Parameters.Add_Int("SIZE_ATTRIB",
125 		"SIZE_DEFAULT"		, _TL("Default Size"),
126 		_TL(""),
127 		1, 1, true
128 	);
129 
130 
131 	//-----------------------------------------------------
132 	// Labeling...
133 
134 	m_Parameters.Add_Choice("LABEL_ATTRIB",
135 		"LABEL_STYLE"		, _TL("Style"),
136 		_TL(""),
137 		CSG_String::Format("%s|%s|%s|%s",
138 			_TL("one label at the polyline centroid"),
139 			_TL("one label at the central vertex of each part"),
140 			_TL("one aligned label at the central vertex of each part"),
141 			_TL("along line labeling")
142 		), 3
143 	);
144 
145 	m_Parameters.Add_Choice("LABEL_STYLE",
146 		"LABEL_ALIGN"		, _TL("Align"),
147 		_TL(""),
148 		CSG_String::Format("%s|%s|%s",
149 			_TL("top"),
150 			_TL("center"),
151 			_TL("bottom")
152 		), 1
153 	);
154 
155 	m_Parameters.Add_Choice("LABEL_STYLE",
156 		"LABEL_ORIENT"		, _TL("Orientation"),
157 		_TL(""),
158 		CSG_String::Format("%s|%s",
159 			_TL("left"),
160 			_TL("right")
161 		), 1
162 	);
163 
164 	m_Parameters.Add_Double("LABEL_STYLE",
165 		"LABEL_FREQUENCY"	, _TL("Along Line Frequency"),
166 		_TL("The distance between labels specified as multiples of the label's text width."),
167 		10., 0., true
168 	);
169 
170 
171 	//-----------------------------------------------------
172 	// Boundary Effect...
173 
174 	m_Parameters.Add_Choice("NODE_DISPLAY",
175 		"BOUNDARY_EFFECT"	, _TL("Boundary Effect"),
176 		_TL(""),
177 		CSG_String::Format("%s|%s|%s|%s|%s|%s|%s|%s|%s|%s",
178 			_TL("none"),
179 			_TL("all sides"),
180 			_TL("top"),
181 			_TL("top left"),
182 			_TL("left"),
183 			_TL("bottom left"),
184 			_TL("bottom"),
185 			_TL("bottom right"),
186 			_TL("right"),
187 			_TL("top right")
188 		), 0
189 	);
190 
191 	m_Parameters.Add_Color("BOUNDARY_EFFECT",
192 		"BOUNDARY_EFFECT_COLOR"	, _TL("Color"),
193 		_TL(""),
194 		SG_GET_RGB(255, 255, 255)
195 	);
196 }
197 
198 
199 ///////////////////////////////////////////////////////////
200 //														 //
201 ///////////////////////////////////////////////////////////
202 
203 //---------------------------------------------------------
On_DataObject_Changed(void)204 void CWKSP_Shapes_Line::On_DataObject_Changed(void)
205 {
206 	AttributeList_Set(m_Parameters("SIZE_ATTRIB"), true);
207 
208 	CWKSP_Shapes::On_DataObject_Changed();
209 }
210 
211 //---------------------------------------------------------
On_Parameters_Changed(void)212 void CWKSP_Shapes_Line::On_Parameters_Changed(void)
213 {
214 	CWKSP_Shapes::On_Parameters_Changed();
215 
216 	//-----------------------------------------------------
217 	m_Size_Type		= m_Parameters("SIZE_TYPE")->asInt();
218 
219 	if(	(m_iSize	= m_Parameters("SIZE_ATTRIB")->asInt()) >= Get_Shapes()->Get_Field_Count()
220 	||	(m_dSize	= Get_Shapes()->Get_Maximum(m_iSize) - (m_Size_Min = Get_Shapes()->Get_Minimum(m_iSize))) <= 0.0 )
221 	{
222 		m_iSize		= -1;
223 		m_Size		= m_Parameters("SIZE_DEFAULT")->asInt();
224 	}
225 	else
226 	{
227 		m_Size		= (int)m_Parameters("SIZE_RANGE")->asRange()->Get_Min();
228 		m_dSize		=     (m_Parameters("SIZE_RANGE")->asRange()->Get_Max() - m_Size) / m_dSize;
229 	}
230 
231 	//-----------------------------------------------------
232 	m_Pen			= wxPen(m_pClassify->Get_Unique_Color(), (int)m_Size, (wxPenStyle)m_Line_Style);
233 
234 	m_bVertices		= m_Parameters("DISPLAY_POINTS")->asInt();
235 
236 	//-----------------------------------------------------
237 	m_Effect_Color	= m_Parameters("BOUNDARY_EFFECT_COLOR")->asColor();
238 
239 	switch( m_Parameters("BOUNDARY_EFFECT")->asInt() )
240 	{
241 	default:	m_Effect	= TEXTEFFECT_NONE       ;	break;
242 	case  1:	m_Effect	= TEXTEFFECT_FRAME      ;	break;
243 	case  2:	m_Effect	= TEXTEFFECT_TOP        ;	break;
244 	case  3:	m_Effect	= TEXTEFFECT_TOPLEFT    ;	break;
245 	case  4:	m_Effect	= TEXTEFFECT_LEFT       ;	break;
246 	case  5:	m_Effect	= TEXTEFFECT_BOTTOMLEFT ;	break;
247 	case  6:	m_Effect	= TEXTEFFECT_BOTTOM     ;	break;
248 	case  7:	m_Effect	= TEXTEFFECT_BOTTOMRIGHT;	break;
249 	case  8:	m_Effect	= TEXTEFFECT_RIGHT      ;	break;
250 	case  9:	m_Effect	= TEXTEFFECT_TOPRIGHT   ;	break;
251 	}
252 }
253 
254 
255 ///////////////////////////////////////////////////////////
256 //														 //
257 ///////////////////////////////////////////////////////////
258 
259 //---------------------------------------------------------
On_Parameter_Changed(CSG_Parameters * pParameters,CSG_Parameter * pParameter,int Flags)260 int CWKSP_Shapes_Line::On_Parameter_Changed(CSG_Parameters *pParameters, CSG_Parameter *pParameter, int Flags)
261 {
262 	//-----------------------------------------------------
263 	if( Flags & PARAMETER_CHECK_ENABLE )
264 	{
265 		if(	pParameter->Cmp_Identifier("SIZE_ATTRIB") )
266 		{
267 			bool	Value	= pParameter->asInt() < Get_Shapes()->Get_Field_Count();
268 
269 			pParameters->Set_Enabled("SIZE_RANGE"  , Value == true);
270 			pParameters->Set_Enabled("SIZE_DEFAULT", Value == false);
271 		}
272 
273 		if(	pParameter->Cmp_Identifier("LABEL_STYLE") )
274 		{
275 			pParameters->Set_Enabled("LABEL_ALIGN"    , pParameter->asInt() == 2 || pParameter->asInt() == 3);
276 			pParameters->Set_Enabled("LABEL_ORIENT"   , pParameter->asInt() == 2 || pParameter->asInt() == 3);
277 			pParameters->Set_Enabled("LABEL_FREQUENCY", pParameter->asInt() == 3);
278 		}
279 
280 		if(	pParameter->Cmp_Identifier("BOUNDARY_EFFECT") )
281 		{
282 			pParameters->Set_Enabled("BOUNDARY_EFFECT_COLOR", pParameter->asInt() != 0);
283 		}
284 	}
285 
286 	return( CWKSP_Shapes::On_Parameter_Changed(pParameters, pParameter, Flags) );
287 }
288 
289 
290 ///////////////////////////////////////////////////////////
291 //														 //
292 ///////////////////////////////////////////////////////////
293 
294 //---------------------------------------------------------
Get_Style_Size(int & min_Size,int & max_Size,double & min_Value,double & dValue,wxString * pName)295 bool CWKSP_Shapes_Line::Get_Style_Size(int &min_Size, int &max_Size, double &min_Value, double &dValue, wxString *pName)
296 {
297 	if( m_iSize >= 0 )
298 	{
299 		min_Size	= (int)(m_Size);
300 		max_Size	= (int)(m_Size + ((Get_Shapes()->Get_Maximum(m_iSize) - m_Size_Min) * m_dSize));
301 		min_Value	= m_Size_Min;
302 		dValue		= m_dSize;
303 
304 		if( pName )
305 		{
306 			pName->Printf(Get_Shapes()->Get_Field_Name(m_iSize));
307 		}
308 
309 		return( true );
310 	}
311 
312 	return( false );
313 }
314 
315 
316 ///////////////////////////////////////////////////////////
317 //														 //
318 ///////////////////////////////////////////////////////////
319 
320 //---------------------------------------------------------
Draw_Initialize(CWKSP_Map_DC & dc_Map,int Flags)321 void CWKSP_Shapes_Line::Draw_Initialize(CWKSP_Map_DC &dc_Map, int Flags)
322 {
323 	m_Label_Style	= m_Parameters("LABEL_STYLE"    )->asInt();
324 	m_Label_Freq	= m_Parameters("LABEL_FREQUENCY")->asInt();
325 	m_Label_Orient	= m_Parameters("LABEL_ORIENT"   )->asInt();
326 
327 	switch( m_Parameters("LABEL_ALIGN")->asInt() )
328 	{
329 	default: m_Label_Align	= TEXTALIGN_TOPLEFT   ;	break;
330 	case  1: m_Label_Align	= TEXTALIGN_CENTERLEFT;	break;
331 	case  2: m_Label_Align	= TEXTALIGN_BOTTOMLEFT;	break;
332 	}
333 
334 	m_Pen.SetStyle((wxPenStyle)(m_Line_Style = PenList_Get_Style("LINE_STYLE")));
335 
336 	dc_Map.dc.SetPen(m_Pen);
337 }
338 
339 //---------------------------------------------------------
Draw_Shape(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape,int Selection)340 void CWKSP_Shapes_Line::Draw_Shape(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape, int Selection)
341 {
342 	wxPen	Pen(m_Pen);
343 
344 	//-----------------------------------------------------
345 	if( Selection )
346 	{
347 		Pen.SetColour(m_Sel_Color);
348 		Pen.SetWidth (m_Size + (Selection == 1 ? 2 : 0));
349 	}
350 
351 	//-----------------------------------------------------
352 	else
353 	{
354 		int		Color;
355 
356 		if( !Get_Class_Color(pShape, Color) && !m_bNoData )
357 		{
358 			return;
359 		}
360 
361 		Pen.SetColour(SG_GET_R(Color), SG_GET_G(Color), SG_GET_B(Color));
362 
363 		//-------------------------------------------------
364 		double	Size	= m_Size;
365 
366 		if( m_iSize >= 0 )
367 		{
368 			if( pShape->is_NoData(m_iSize) )
369 			{
370 				if( !m_bNoData )
371 				{
372 					return;
373 				}
374 			}
375 			else
376 			{
377 				Size	+= m_dSize * (pShape->asDouble(m_iSize) - m_Size_Min);
378 			}
379 		}
380 
381 		switch( m_Size_Type )
382 		{
383 		default: Size *= dc_Map.m_Scale   ; break;
384 		case  1: Size *= dc_Map.m_World2DC; break;
385 		}
386 
387 		Pen.SetWidth(Size < 0 ? 0 : (int)(0.5 + Size));
388 	}
389 
390 	//-----------------------------------------------------
391 	if( m_Effect )
392 	{
393 		wxColour	Color	= Pen.GetColour();	Pen.SetColour(m_Effect_Color);	dc_Map.dc.SetPen(Pen);
394 
395 		if( m_Effect & TEXTEFFECT_TOP         )	_Draw_Shape(dc_Map, pShape,  0, -1);
396 		if( m_Effect & TEXTEFFECT_TOPLEFT     )	_Draw_Shape(dc_Map, pShape, -1, -1);
397 		if( m_Effect & TEXTEFFECT_LEFT        )	_Draw_Shape(dc_Map, pShape, -1,  0);
398 		if( m_Effect & TEXTEFFECT_BOTTOMLEFT  )	_Draw_Shape(dc_Map, pShape, -1,  1);
399 		if( m_Effect & TEXTEFFECT_BOTTOM      )	_Draw_Shape(dc_Map, pShape,  0,  1);
400 		if( m_Effect & TEXTEFFECT_BOTTOMRIGHT )	_Draw_Shape(dc_Map, pShape,  1,  1);
401 		if( m_Effect & TEXTEFFECT_RIGHT       )	_Draw_Shape(dc_Map, pShape,  1,  0);
402 		if( m_Effect & TEXTEFFECT_TOPRIGHT    )	_Draw_Shape(dc_Map, pShape,  1, -1);
403 
404 		Pen.SetColour(Color);
405 	}
406 
407 	//-----------------------------------------------------
408 	dc_Map.dc.SetPen(Pen);
409 
410 	_Draw_Shape(dc_Map, pShape);
411 
412 	dc_Map.dc.SetPen(m_Pen);
413 }
414 
415 //---------------------------------------------------------
_Draw_Shape(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape,int xOffset,int yOffset)416 void CWKSP_Shapes_Line::_Draw_Shape(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape, int xOffset, int yOffset)
417 {
418 	for(int iPart=0; iPart<pShape->Get_Part_Count(); iPart++)
419 	{
420 		if( pShape->Get_Point_Count(iPart) > 1 )
421 		{
422 			TSG_Point_Int A = dc_Map.World2DC(pShape->Get_Point(0, iPart)); A.x += xOffset; A.y += yOffset;
423 
424 			for(int iPoint=1; iPoint<pShape->Get_Point_Count(iPart); iPoint++)
425 			{
426 				TSG_Point_Int B = A; A = dc_Map.World2DC(pShape->Get_Point(iPoint, iPart)); A.x += xOffset; A.y += yOffset;
427 
428 				dc_Map.dc.DrawLine(A.x, A.y, B.x, B.y);
429 			}
430 		}
431 	}
432 }
433 
434 //---------------------------------------------------------
435 #define GET_ANGLE(a, b)	M_RAD_TO_DEG * (b.x != a.x ? M_PI_180 - atan2((double)(b.y - a.y), (double)(b.x - a.x)) : (b.y > a.y ? M_PI_270 : (b.y < a.y ? M_PI_090 : 0.0)))
436 
437 //---------------------------------------------------------
Draw_Label(CWKSP_Map_DC & dc_Map,CSG_Shape * pShape,const wxString & Label)438 void CWKSP_Shapes_Line::Draw_Label(CWKSP_Map_DC &dc_Map, CSG_Shape *pShape, const wxString &Label)
439 {
440 	CSG_Shape_Line	*pLine	= (CSG_Shape_Line *)pShape;
441 
442 	switch( m_Label_Style )
443 	{
444 	//-----------------------------------------------------
445 	case  0:	// one label at the polyline centroid
446 	{
447 		TSG_Point_Int	C	= dc_Map.World2DC(pLine->Get_Centroid());
448 
449 		Draw_Text(dc_Map.dc, TEXTALIGN_CENTER, C.x, C.y, Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
450 	} break;
451 
452 	//-----------------------------------------------------
453 	case  1:	// one label at the central vertex of each part
454 	case  2:	// one aligned label at the central vertex of each part
455 	{
456 		for(int iPart=0; iPart<pLine->Get_Part_Count(); iPart++)
457 		{
458 			double	d = 0.0, c = 0.5 * pLine->Get_Length(iPart);
459 
460 			TSG_Point	A = pLine->Get_Point(0, iPart);
461 
462 			for(int i=1, j=0; d<c && i<pLine->Get_Point_Count(iPart); i++, j++)
463 			{
464 				d	+= SG_Get_Distance(pLine->Get_Point(i, iPart), pLine->Get_Point(j, iPart));
465 
466 				if( d >= c )
467 				{
468 					if( m_Label_Style == 1 )
469 					{
470 						TSG_Point	A	= pLine->Get_Point(i, iPart);
471 						TSG_Point	B	= pLine->Get_Point(j, iPart);
472 
473 						A.x	+= 0.5 * (B.x - A.x);
474 						A.y	+= 0.5 * (B.y - A.y);
475 
476 						TSG_Point_Int	C	= dc_Map.World2DC(A);
477 
478 						Draw_Text(dc_Map.dc, TEXTALIGN_CENTER, C.x, C.y, Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
479 					}
480 					else
481 					{
482 						TSG_Point_Int	A	= dc_Map.World2DC(pLine->Get_Point(i, iPart));
483 						TSG_Point_Int	B	= dc_Map.World2DC(pLine->Get_Point(j, iPart));
484 
485 						if( m_Label_Orient == 0 )
486 						{
487 							Draw_Text(dc_Map.dc, m_Label_Align, A.x, A.y, GET_ANGLE(B, A), Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
488 						}
489 						else
490 						{
491 							Draw_Text(dc_Map.dc, m_Label_Align, B.x, B.y, GET_ANGLE(A, B), Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
492 						}
493 					}
494 				}
495 			}
496 		}
497 	} break;
498 
499 	//-----------------------------------------------------
500 	case  3:	// along line labeling
501 	{
502 		wxCoord	Width, Height;	dc_Map.dc.GetTextExtent(Label, &Width, &Height);
503 
504 		for(int iPart=0; iPart<pLine->Get_Part_Count(); iPart++)
505 		{
506 			if( pLine->Get_Point_Count(iPart) < 2 || Width > dc_Map.m_World2DC * pLine->Get_Length(iPart) )
507 			{
508 				continue;
509 			}
510 
511 			bool			bLabel	= false;
512 			double			d		= 0.0;
513 			TSG_Point_Int	B, A	= dc_Map.World2DC(pLine->Get_Point(0, iPart));
514 
515 			for(int iPoint=1; iPoint<pLine->Get_Point_Count(iPart); iPoint++)
516 			{
517 				//-----------------------------------------
518 				if( !bLabel )
519 				{
520 					B	= A; A	= dc_Map.World2DC(pLine->Get_Point(iPoint, iPart));
521 
522 					if( (d += SG_Get_Distance(A.x, A.y, B.x, B.y)) > m_Label_Freq * Width )
523 					{
524 						B	= A; bLabel	= true;
525 					}
526 				}
527 
528 				//-----------------------------------------
529 				else
530 				{
531 					A	= dc_Map.World2DC(pLine->Get_Point(iPoint, iPart));
532 
533 					if( SG_Get_Distance(A.x, A.y, B.x, B.y) > Width )
534 					{
535 						d	= 0.0;	bLabel	= false;
536 
537 						if( m_Label_Orient == 0 )
538 						{
539 							Draw_Text(dc_Map.dc, m_Label_Align, A.x, A.y, GET_ANGLE(B, A), Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
540 						}
541 						else
542 						{
543 							Draw_Text(dc_Map.dc, m_Label_Align, B.x, B.y, GET_ANGLE(A, B), Label, m_Label_Eff, m_Label_Eff_Color, m_Label_Eff_Size);
544 						}
545 					}
546 				}
547 			}
548 		}
549 	} break;
550 	}
551 }
552 
553 
554 ///////////////////////////////////////////////////////////
555 //														 //
556 ///////////////////////////////////////////////////////////
557 
558 //---------------------------------------------------------
Edit_Shape_Draw_Move(wxDC & dc,const CSG_Rect & rWorld,const wxPoint & Point)559 void CWKSP_Shapes_Line::Edit_Shape_Draw_Move(wxDC &dc, const CSG_Rect &rWorld, const wxPoint &Point)
560 {
561 	if( m_Edit_pShape && m_Edit_iPart >= 0 )
562 	{
563 		int	nPoints	= m_Edit_pShape->Get_Point_Count(m_Edit_iPart);
564 
565 		if( m_Edit_iPoint < 0 )
566 		{
567 			if( nPoints > 0 )
568 			{
569 				CWKSP_Shapes::Edit_Shape_Draw_Move(dc, rWorld, Point,
570 					m_Edit_pShape->Get_Point(nPoints - 1, m_Edit_iPart)
571 				);
572 			}
573 		}
574 		else
575 		{
576 			if( nPoints > 1 )
577 			{
578 				if( m_Edit_iPoint > 0 )
579 				{
580 					CWKSP_Shapes::Edit_Shape_Draw_Move(dc, rWorld, Point,
581 						m_Edit_pShape->Get_Point(m_Edit_iPoint - 1, m_Edit_iPart)
582 					);
583 				}
584 
585 				if( m_Edit_iPoint < nPoints - 1 )
586 				{
587 					CWKSP_Shapes::Edit_Shape_Draw_Move(dc, rWorld, Point,
588 						m_Edit_pShape->Get_Point(m_Edit_iPoint + 1, m_Edit_iPart)
589 					);
590 				}
591 			}
592 
593 			CWKSP_Shapes::Edit_Shape_Draw_Move(dc, rWorld, Point);
594 		}
595 	}
596 }
597 
598 //---------------------------------------------------------
Edit_Shape_Draw(CWKSP_Map_DC & dc_Map)599 void CWKSP_Shapes_Line::Edit_Shape_Draw(CWKSP_Map_DC &dc_Map)
600 {
601 	if( m_Edit_pShape )
602 	{
603 		if( m_Edit_bGleam )
604 		{
605 			dc_Map.dc.SetPen(wxPen(m_Edit_Color, 3));
606 			dc_Map.dc.SetLogicalFunction(wxINVERT);
607 
608 			_Draw_Shape(dc_Map, m_Edit_pShape);
609 
610 			dc_Map.dc.SetLogicalFunction(wxCOPY);
611 		}
612 
613 		dc_Map.dc.SetPen(wxPen(m_Edit_Color));
614 
615 		_Draw_Shape(dc_Map, m_Edit_pShape);
616 
617 		CWKSP_Shapes::Edit_Shape_Draw(dc_Map);
618 	}
619 }
620 
621 //---------------------------------------------------------
Edit_Shape_HitTest(CSG_Point pos_Point,double max_Dist,int & pos_iPart,int & pos_iPoint)622 int CWKSP_Shapes_Line::Edit_Shape_HitTest(CSG_Point pos_Point, double max_Dist, int &pos_iPart, int &pos_iPoint)
623 {
624 	int			Result, iPart, iPoint;
625 	double		d;
626 	TSG_Point	A, B, Point, hit_Point;
627 
628 	Result	= CWKSP_Shapes::Edit_Shape_HitTest(pos_Point, max_Dist, pos_iPart, pos_iPoint);
629 
630 	if( Result == 0 && m_Edit_pShape )
631 	{
632 		for(iPart=0; iPart<m_Edit_pShape->Get_Part_Count(); iPart++)
633 		{
634 			B	= m_Edit_pShape->Get_Point(0, iPart);
635 
636 			for(iPoint=1; iPoint<m_Edit_pShape->Get_Point_Count(iPart); iPoint++)
637 			{
638 				A	= m_Edit_pShape->Get_Point(iPoint, iPart);
639 				d	= SG_Get_Nearest_Point_On_Line(pos_Point, A, B, Point, true);
640 				B	= A;
641 
642 				if( d >= 0.0 && (0.0 > max_Dist || d < max_Dist) )
643 				{
644 					Result		= 2;
645 					max_Dist	= d;
646 					pos_iPoint	= iPoint;
647 					pos_iPart	= iPart;
648 					hit_Point	= Point;
649 				}
650 			}
651 		}
652 
653 		if( Result )
654 		{
655 			pos_Point	= hit_Point;
656 		}
657 	}
658 
659 	return( Result );
660 }
661 
662 //---------------------------------------------------------
Edit_Snap_Point_ToLine(CSG_Point pos_Point,CSG_Point & snap_Point,double & snap_Dist,CSG_Shape * pShape)663 void CWKSP_Shapes_Line::Edit_Snap_Point_ToLine(CSG_Point pos_Point, CSG_Point &snap_Point, double &snap_Dist, CSG_Shape *pShape)
664 {
665 	int			iPart, iPoint;
666 	double		d;
667 	TSG_Point	A, B, Point;
668 
669 	for(iPart=0; iPart<pShape->Get_Part_Count(); iPart++)
670 	{
671 		B	= pShape->Get_Point(0, iPart);
672 
673 		for(iPoint=1; iPoint<pShape->Get_Point_Count(iPart); iPoint++)
674 		{
675 			A	= pShape->Get_Point(iPoint, iPart);
676 			d	= SG_Get_Nearest_Point_On_Line(pos_Point, A, B, Point, true);
677 			B	= A;
678 
679 			if( d >= 0.0 && d < snap_Dist )
680 			{
681 				snap_Dist	= d;
682 				snap_Point	= Point;
683 			}
684 		}
685 	}
686 }
687 
688 
689 ///////////////////////////////////////////////////////////
690 //														 //
691 //														 //
692 //														 //
693 ///////////////////////////////////////////////////////////
694 
695 //---------------------------------------------------------
696