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