wxArt2D
polygon.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/polygon.cpp
2  \author Klaas Holwerda
3 
4  Copyright: 2000-2004 (c) Klaas Holwerda
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: polygon.cpp,v 1.209 2009/07/24 16:35:01 titato Exp $
9 */
10 
11 #include "a2dprec.h"
12 
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16 
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #endif
20 
21 #include "wx/canvas/polygon.h"
22 
23 #include <float.h>
24 #include "wx/canvas/canobj.h"
25 #include "wx/canvas/drawer.h"
26 #include "wx/canvas/drawing.h"
27 #include "wx/canvas/canprim.h"
28 #include "wx/canvas/tools.h"
29 #include "wx/canvas/canglob.h"
30 
31 #if defined(__WXMSW__) && defined(__MEMDEBUG__)
32 #include <wx/msw/msvcrt.h>
33 #endif
34 
35 
36 IMPLEMENT_DYNAMIC_CLASS( a2dPolyHandleL, a2dHandle )
37 
38 IMPLEMENT_DYNAMIC_CLASS( a2dPolygonL, a2dCanvasObject )
39 IMPLEMENT_DYNAMIC_CLASS( a2dPolylineL, a2dPolygonL )
40 
41 IMPLEMENT_DYNAMIC_CLASS( a2dPolygonLClipper, a2dPolygonL )
42 IMPLEMENT_DYNAMIC_CLASS( a2dPolygonLClipper2, a2dPolygonL )
43 
44 static inline double sqr( double x ) { return x * x; }
45 
46 static double PointDistSqr( double x1, double y1, double x2, double y2 )
47 {
48  double dx = x1 - x2;
49  double dy = y1 - y2;
50  return sqr( dx ) + sqr( dy );
51 }
52 
53 //----------------------------------------------------------------------------
54 // a2dPolygonL
55 //----------------------------------------------------------------------------
56 
57 #define a2dCrossAtVertexSize 2
58 
59 bool a2dPolygonL::m_allowCrossAtVertex = false;
60 
61 BEGIN_EVENT_TABLE( a2dPolygonL, a2dCanvasObject )
62  EVT_CANVASOBJECT_MOUSE_EVENT( a2dPolygonL::OnCanvasObjectMouseEvent )
64  EVT_CANVASHANDLE_MOUSE_EVENT_ENTER( a2dPolygonL::OnHandleEventEnter )
65  EVT_CANVASHANDLE_MOUSE_EVENT_LEAVE( a2dPolygonL::OnHandleEventLeave )
68  EVT_CHAR( a2dPolygonL::OnChar )
69 END_EVENT_TABLE()
70 
72  :
73  m_crossAtVertex( false ),
74  m_spline( false ),
75  m_contourwidth( 0 ),
77 {
78  m_lsegments = new a2dVertexList();
79 }
80 
81 a2dPolygonL::a2dPolygonL( a2dVertexListPtr points, bool spline )
82  :
83  m_spline( spline ),
84  m_contourwidth( 0 ),
85  m_crossAtVertex( false ),
87 {
88  m_lsegments = points;
89 }
90 
91 a2dPolygonL::~a2dPolygonL()
92 {
93 }
94 
96 {
97  m_lsegments->clear();
98 }
99 
100 a2dPolygonL::a2dPolygonL( const a2dPolygonL& other, CloneOptions options, a2dRefMap* refs )
101  : a2dCanvasObject( other, options, refs )
102 {
103  m_lsegments = new a2dVertexList();
104  *m_lsegments = *other.m_lsegments;
105  m_spline = other.m_spline;
107  m_crossAtVertex = other.m_crossAtVertex;
108 }
109 
111 {
112  return new a2dPolygonL( *this, options, refs );
113 }
114 
115 a2dVertexList* a2dPolygonL::GetAsVertexList( bool& returnIsPolygon ) const
116 {
117  if ( m_contourwidth )
118  {
119  a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth / 2, a2dPATH_END_ROUND );
120  if ( !returnIsPolygon )
121  contourpoints->push_back( contourpoints->front()->Clone() );
122  return contourpoints;
123  }
124  else
125  {
126  a2dVertexList* contourpoints = new a2dVertexList( *(m_lsegments.Get()) );
127  if ( !returnIsPolygon )
128  contourpoints->push_back( contourpoints->front()->Clone() );
129  return contourpoints;
130  }
131 }
132 
134 {
135  a2dVpath* segments = m_lsegments->ConvertToVpath( true, true );
136  a2dVectorPath* canpath = new a2dVectorPath( segments );
137  if ( transform )
138  segments->Transform( m_lworld );
139  canpath->SetStroke( this->GetStroke() );
140  canpath->SetFill( this->GetFill() );
141  canpath->SetLayer( m_layer );
142  canpath->SetContourWidth( GetContourWidth() );
143  a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
144  canpathlist->push_back( canpath );
145  return canpathlist;
146 }
147 
149 {
150  a2dVpath* segments = new a2dVpath();
151  a2dVectorPath* snappath = new a2dVectorPath( segments );
152  a2dCanvasObjectList* snappathlist = new a2dCanvasObjectList();
153  snappathlist->push_back( snappath );
154 
155  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
157  )
158  {
160  {
162  {
163  a2dCanvasObject* obj = *iter;
164  a2dPin* pin = wxDynamicCast( obj, a2dPin );
165  if ( pin && !pin->GetRelease( ) )
166  {
167  if ( snapToWhat & a2dRestrictionEngine::snapToPins ||
168  ( snapToWhat & a2dRestrictionEngine::snapToPinsUnconnected && !pin->IsConnectedTo() )
169  )
170  {
171  a2dVpathSegment* seg = new a2dVpathSegment( pin->GetAbsX(), pin->GetAbsY(), a2dPATHSEG_MOVETO );
172  segments->Add( seg );
173  }
174  }
175  }
176  }
177  }
178 
179  if ( snapToWhat & a2dRestrictionEngine::snapToObjectPos )
180  {
182  segments->Add( seg );
183  }
184 
186  {
187  a2dVpath* segments = m_lsegments->ConvertToVpath( true, true );
188  a2dVectorPath* snappathvertex = new a2dVectorPath( segments );
189  segments->Transform( m_lworld );
190  snappathlist->push_back( snappathvertex );
191  }
192 
193  return snappathlist;
194 }
195 
196 a2dCanvasObjectList* a2dPolygonL::GetAsLinesArcs( bool transform )
197 {
198  a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
199 
200  double xp = m_lsegments->back()->m_x;
201  double yp = m_lsegments->back()->m_y;
202  if ( transform )
203  m_lworld.TransformPoint( xp, yp, xp, yp );
204  a2dCanvasObject* obj;
205  for( a2dVertexList::iterator iter = m_lsegments->begin(); iter != m_lsegments->end(); ++iter )
206  {
207  double x, y, xm, ym;
208  a2dLineSegment* seg = *iter;
209  x = seg->m_x; y = seg->m_y;
210  if ( transform )
211  m_lworld.TransformPoint( x, y, x, y );
212  if ( seg->GetArc() )
213  {
214  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
215  xm = cseg->m_x2; ym = cseg->m_y2;
216  if ( transform )
217  m_lworld.TransformPoint( xm, ym, xm, ym );
218  a2dArc* arc = new a2dArc();
219  arc->SetChord( true );
220  obj = arc;
221  arc->Set( xp, yp, xm, ym, x, y );
222  linesAnArcs->push_back( arc );
223  }
224  else
225  {
226  a2dSLine* line = new a2dSLine( xp, yp, x, y );
227  obj = line;
228  linesAnArcs->push_back( line );
229  }
230 
231  obj->SetStroke( this->GetStroke() );
232  obj->SetFill( this->GetFill() );
233  obj->SetLayer( m_layer );
235  obj->SetRoot( m_root, false );
236 
237  xp = x;
238  yp = y;
239  }
240 
241  return linesAnArcs;
242 }
243 
244 bool a2dPolygonL::RestrictToObject( a2dIterC& ic, const a2dPoint2D& pointToSnapTo, a2dPoint2D& bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld )
245 {
246  // object has disabled snap?
247  if ( !m_flags.m_snap_to )
248  return false;
249 
250  double StrokeExtend = 0;
251  a2dStroke stroke = GetStroke();
252 
253  if ( stroke.IsNoStroke() ) //IsNoStroke() stroke means use layer
254  {
255  if ( m_root && m_root->GetLayerSetup() )
256  {
257  a2dStroke layerpen = m_root->GetLayerSetup()->GetStroke( m_layer );
258  if ( layerpen.GetPixelStroke() )
259  StrokeExtend = layerpen.GetWidth() / 2;
260  else
261  StrokeExtend = layerpen.GetWidth() / 2;
262  }
263  }
264  else if ( !stroke.IsSameAs( *a2dTRANSPARENT_STROKE ) )
265  {
266  if ( stroke.GetPixelStroke() )
267  {
268  StrokeExtend = ic.GetDrawer2D()->DeviceToWorldXRel( stroke.GetWidth() / 2 );
269  }
270  else
271  StrokeExtend = stroke.GetWidth() / 2;
272  }
273  ic.SetStrokeWorldExtend( StrokeExtend );
274 
275  bool res = false;
276  if ( snapToWhat & a2dRestrictionEngine::snapToObjectVertexes ||
280  )
281  {
282  a2dVertexList::iterator iter = m_lsegments->begin();
283  double lastx, lasty;
284  if ( iter != m_lsegments->end() )
285  m_lworld.TransformPoint( m_lsegments->back()->m_x, m_lsegments->back()->m_y, lastx, lasty );
286  a2dLineSegment* seg;
287  while ( iter != m_lsegments->end() )
288  {
289  seg = ( *iter );
290 
291  double x, y;
292  m_lworld.TransformPoint( seg->m_x, seg->m_y, x, y );
293  a2dPoint2D p2( x, y );
294 
295  if ( snapToWhat & a2dRestrictionEngine::snapToObjectIntersection )
296  {
297  }
299  {
300  a2dPoint2D p1( lastx, lasty );
301  a2dLine line( p1, p2 );
302  a2dPoint2D pBestPoint;
303  double dist = line.PointDistance( pointToSnapTo, &pBestPoint );
304  double pw = ic.GetWorldStrokeExtend();
305  if( dist < thresHoldWorld + pw )
306  res |= SetPointIfCloser( pointToSnapTo, pBestPoint, bestPointSofar, thresHoldWorld + pw );
307  }
309  {
310  res |= SetPointIfCloser( pointToSnapTo, a2dPoint2D( x + lastx / 2.0, y + lasty / 2.0 ), bestPointSofar, thresHoldWorld );
311  }
313  {
314  //if within the threshold, do snap to vertex position.
315  res |= SetPointIfCloser( pointToSnapTo, p2, bestPointSofar, thresHoldWorld );
316  }
317  lastx = x; lasty = y;
318  iter++;
319  }
320  }
321 
322  snapToWhat = snapToWhat & ( a2dRestrictionEngine::snapToAll ^ a2dRestrictionEngine::snapToObjectVertexes ); //disable this for base now.
323 
324  return res || a2dCanvasObject::RestrictToObject( ic, pointToSnapTo, bestPointSofar, snapToWhat, thresHoldWorld );
325 }
326 
327 int a2dPolygonL::GetIndexSegment( a2dLineSegmentPtr seg )
328 {
329  if ( seg.Get() == NULL )
330  {
331  if ( !m_lsegments->empty() )
332  return m_lsegments->IndexOf( m_lsegments->back() );
333  return -1;
334  }
335  else
336  {
337  return m_lsegments->IndexOf( seg );
338  }
339 }
340 
341 a2dVertexList::iterator a2dPolygonL::GetSegmentAtIndex( unsigned int index )
342 {
343  return m_lsegments->item( index );
344 }
345 
346 a2dVertexList* a2dPolygonL::GetSegmentListAtIndex( unsigned int index )
347 {
348  if ( index < m_lsegments->size() + 1 )
349  {
350  return m_lsegments;
351  }
352  return NULL;
353 }
354 
355 
356 a2dLineSegment* a2dPolygonL::AddPoint( double x, double y, a2dLineSegmentPtr seg, bool afterinversion )
357 {
358  if ( afterinversion )
359  {
360  a2dAffineMatrix inverse = m_lworld;
361  inverse.Invert();
362  inverse.TransformPoint( x, y, x, y );
363  }
364 
365  a2dLineSegment* point = new a2dLineSegment( x, y );
366 
367  if ( seg.Get() == NULL )
368  m_lsegments->push_back( point );
369  else
370  {
371  a2dVertexList::iterator iter = m_lsegments->begin();
372  while ( iter != m_lsegments->end() )
373  {
374  if ( ( *iter ) == seg )
375  {
376  m_lsegments->insert( iter, point );
377  break;
378  }
379  ++iter;
380  }
381  }
382 
383  SetPending( true );
384  return point;
385 }
386 
387 a2dLineSegment* a2dPolygonL::AddPoint( const a2dPoint2D& P, int index, bool afterinversion )
388 {
389  return AddPoint( P.m_x, P.m_y, index, afterinversion );
390 }
391 
392 a2dLineSegment* a2dPolygonL::AddPoint( double x, double y, int index, bool afterinversion )
393 {
394  if ( afterinversion )
395  {
396  a2dAffineMatrix inverse = m_lworld;
397  inverse.Invert();
398  inverse.TransformPoint( x, y, x, y );
399  }
400 
401  a2dLineSegment* point = new a2dLineSegment( x, y );
402 
403  if ( index == -1 )
404  m_lsegments->push_back( point );
405  else
406  {
407  a2dVertexList::iterator iter = m_lsegments->begin();
408  int i = 0;
409  while ( i < index ) { ++iter; i++; }
410  m_lsegments->insert( iter, point );
411  }
412 
413  SetPending( true );
414  return point;
415 }
416 
418 {
419  a2dVertexList::iterator iterp = m_lsegments->end();
420  a2dVertexList::iterator iterpp = m_lsegments->end();
421  a2dVertexList::iterator iter = m_lsegments->begin();
422 
423  int inode;
424 
425  // remove equal points
426  iter = m_lsegments->begin();
427  inode = 0;
428  if( iter != m_lsegments->end() )
429  {
430  iterp = iter++;
431  inode++;
432  }
433  while ( iter != m_lsegments->end() )
434  {
435  a2dLineSegment* line1 = *iterp;
436  a2dLineSegment* line2 = *iter;
437  if( line1->GetPoint() == line2->GetPoint() && !line1->GetArc() ) //this is arc save on line2
438  {
439  if( sendCommandsTo )
440  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode ) );
441  m_lsegments->erase( iterp );
442  }
443  else
444  {
445  inode++;
446  }
447 
448  iterp = iter++;
449  }
450 
451  //remove points on same x/y
452  iter = m_lsegments->begin();
453  inode = 0;
454  if( iter != m_lsegments->end() )
455  {
456  iterp = iter++;
457  inode++;
458  }
459  if( iter != m_lsegments->end() )
460  {
461  iterpp = iterp;
462  iterp = iter++;
463  inode++;
464  }
465  while ( iter != m_lsegments->end() )
466  {
467  a2dLineSegment* point0 = *iterpp;
468  a2dLineSegment* point1 = *iterp;
469  a2dLineSegment* point2 = *iter;
470 
471  if ( !point0->GetArc() && !point1->GetArc() &&
472  ( ( point1->GetPoint().m_x == point0->GetPoint().m_x && point1->GetPoint().m_x == point2->GetPoint().m_x ) ||
473  ( point1->GetPoint().m_y == point0->GetPoint().m_y && point1->GetPoint().m_y == point2->GetPoint().m_y )
474  )
475  )
476  {
477  if( sendCommandsTo )
478  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode -1 ) );
479  m_lsegments->erase( iterp );
480  }
481  else
482  {
483  inode++;
484  iterpp = iterp;
485  }
486  iterp = iter++;
487  }
488 
489  /*
490  // remove 180 deg points
491  iter = m_lsegments->begin();
492  inode = 0;
493  if( iter != m_lsegments->end() )
494  {
495  iterp = iter++;
496  inode++;
497  }
498  if( iter != m_lsegments->end() )
499  {
500  iterpp = iterp;
501  iterp = iter++;
502  inode++;
503  }
504  while ( iter != m_lsegments->end() )
505  {
506  a2dLineSegment* point0 = *iterpp;
507  a2dLineSegment* point1 = *iterp;
508  a2dLineSegment* point2 = *iter;
509 
510  double dx10 = point1->m_x - point0->m_x;
511  double dy10 = point1->m_y - point0->m_y;
512  double dx21 = point2->m_x - point1->m_x;
513  double dy21 = point2->m_y - point1->m_y;
514 
515  if( !point0->GetArc() && !point1->GetArc() && dx10* dy21 - dx21* dy10 == 0 )
516  {
517  if( sendCommandsTo )
518  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode - 1 ) );
519  m_lsegments->erase( iterp );
520  }
521  else
522  {
523  inode++;
524  iterpp = iterp;
525  }
526  iterp = iter++;
527  }
528  */
529 }
530 
531 void a2dPolygonL::RemoveSegment( double& x, double& y , a2dLineSegmentPtr seg, bool transformed )
532 {
533  if ( seg.Get() == NULL )
534  {
535  a2dLineSegment* point;
536  point = m_lsegments->back();
537  x = point->m_x;
538  y = point->m_y;
539  m_lsegments->pop_back();
540  }
541  else
542  {
543  a2dVertexList::iterator iter = m_lsegments->begin();
544  a2dLineSegment* point;
545  while ( iter != m_lsegments->end() )
546  {
547  if ( *iter == seg )
548  {
549  point = ( *iter );
550  x = point->m_x;
551  y = point->m_y;
552  m_lsegments->erase( iter );
553  break;
554  }
555  iter++;
556  }
557  }
558 
559  if ( transformed )
560  {
561  m_lworld.TransformPoint( x, y, x, y );
562  }
563 
564  SetPending( true );
565 }
566 
567 void a2dPolygonL::RemoveSegment( double& x, double& y , int index, bool transformed )
568 {
569  if ( index == -1 )
570  {
571  a2dLineSegment* point;
572  point = m_lsegments->back();
573  x = point->m_x;
574  y = point->m_y;
575  m_lsegments->pop_back();
576  }
577  else
578  {
579  int i = 0;
580  a2dVertexList::iterator iter = m_lsegments->begin();
581  a2dLineSegment* point;
582  while ( iter != m_lsegments->end() )
583  {
584  if ( i == index )
585  {
586  point = ( *iter );
587  x = point->m_x;
588  y = point->m_y;
589  m_lsegments->erase( iter );
590  break;
591  }
592  i++;
593  iter++;
594  }
595  }
596 
597  if ( transformed )
598  {
599  m_lworld.TransformPoint( x, y, x, y );
600  }
601 
602  SetPending( true );
603 }
604 
605 void a2dPolygonL::GetPosXYSegment( int index, double& x, double& y, bool transform ) const
606 {
607  if ( index == 0 )
608  {
609  a2dLineSegment* point;
610  point = m_lsegments->front();
611  x = point->m_x;
612  y = point->m_y;
613  }
614  else if ( index == -1 || index == m_lsegments->size() - 1 )
615  {
616  a2dLineSegment* point;
617  point = m_lsegments->back();
618  x = point->m_x;
619  y = point->m_y;
620  }
621  else
622  {
623  int i = 0;
624  a2dVertexList::iterator iter = m_lsegments->begin();
625  a2dLineSegment* point;
626  while ( iter != m_lsegments->end() )
627  {
628  if ( i == index )
629  {
630  point = ( *iter );
631  x = point->m_x;
632  y = point->m_y;
633  break;
634  }
635  i++;
636  iter++;
637  }
638  }
639 
640  if ( transform )
641  {
642  m_lworld.TransformPoint( x, y, x, y );
643  }
644 }
645 
646 void a2dPolygonL::GetPosXYSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
647 {
648  if ( seg.Get() == NULL )
649  {
650  a2dLineSegment* point;
651  point = m_lsegments->back();
652  x = point->m_x;
653  y = point->m_y;
654  }
655  else
656  {
657  x = seg->m_x;
658  y = seg->m_y;
659  }
660 
661  if ( transform )
662  {
663  m_lworld.TransformPoint( x, y, x, y );
664  }
665 }
666 
667 void a2dPolygonL::GetPosXYMidSegment( int index, double& x, double& y, bool transform ) const
668 {
669  if ( index == -1 )
670  {
671  a2dLineSegment* seg = m_lsegments->back();
672  wxASSERT_MSG( seg->GetArc() , _T( "this is not an arc segment." ) );
673  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
674  x = cseg->m_x2;
675  y = cseg->m_y2;
676  }
677  else
678  {
679  int i = 0;
680  a2dVertexList::iterator iter = m_lsegments->begin();
681  a2dLineSegment* seg;
682  while ( iter != m_lsegments->end() )
683  {
684  if ( i == index )
685  {
686  seg = ( *iter );
687  wxASSERT_MSG( seg->GetArc() , _T( "this is not an arc segment." ) );
688  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
689  x = cseg->m_x2;
690  y = cseg->m_y2;
691  break;
692  }
693  i++;
694  iter++;
695  }
696  }
697 
698  if ( transform )
699  {
700  m_lworld.TransformPoint( x, y, x, y );
701  }
702 }
703 
704 void a2dPolygonL::GetPosXYMidSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
705 {
706  if ( seg.Get() == NULL )
707  {
708  a2dLineSegment* seg = m_lsegments->back();
709  wxASSERT_MSG( seg->GetArc() , _T( "this is not an arc segment." ) );
710  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
711  x = cseg->m_x2;
712  y = cseg->m_y2;
713  }
714  else
715  {
716  wxASSERT_MSG( seg->GetArc() , _T( "this is not an arc segment." ) );
717  a2dArcSegment* cseg = ( a2dArcSegment* ) seg.Get();
718  x = cseg->m_x2;
719  y = cseg->m_y2;
720  }
721 
722  if ( transform )
723  {
724  m_lworld.TransformPoint( x, y, x, y );
725  }
726 }
727 
728 void a2dPolygonL::SetPosXYSegment( int n, double x, double y, bool afterinversion )
729 {
730  if ( afterinversion )
731  {
732  a2dAffineMatrix inverse = m_lworld;
733  inverse.Invert();
734  inverse.TransformPoint( x, y, x, y );
735  }
736 
737  m_lsegments->SetPointAdjustArcs( n, x, y, true );
738  SetPending( true );
739 }
740 
741 void a2dPolygonL::SetPosXYSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
742 {
743  if ( afterinversion )
744  {
745  a2dAffineMatrix inverse = m_lworld;
746  inverse.Invert();
747  inverse.TransformPoint( x, y, x, y );
748  }
749 
750  m_lsegments->SetPointAdjustArcs( seg, x, y, true );
751  SetPending( true );
752 }
753 
754 void a2dPolygonL::SetPosXYMidSegment( int index, double x, double y, bool afterinversion )
755 {
756  if ( afterinversion )
757  {
758  a2dAffineMatrix inverse = m_lworld;
759  inverse.Invert();
760  inverse.TransformPoint( x, y, x, y );
761  }
762 
763  a2dVertexList::iterator iterp = m_lsegments->end()--;
764  a2dVertexList::iterator iter = m_lsegments->begin();
765  a2dLineSegment* seg;
766  int i = 0;
767  while ( iter != m_lsegments->end() )
768  {
769  seg = ( *iter );
770  if ( i == index )
771  {
772  wxASSERT_MSG( seg->GetArc() , _T( "this is not an arc segment." ) );
773  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
774  cseg->SetMidPoint( *( *iterp ), x, y );
775  break;
776  }
777  i++;
778  iterp = iter;
779  iter++;
780  }
781  SetPending( true );
782 }
783 
784 void a2dPolygonL::SetPosXYMidSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
785 {
786  if ( afterinversion )
787  {
788  a2dAffineMatrix inverse = m_lworld;
789  inverse.Invert();
790  inverse.TransformPoint( x, y, x, y );
791  }
792 
793  a2dVertexList::iterator iterp = m_lsegments->end()--;
794  a2dVertexList::iterator iter = m_lsegments->begin();
795  a2dLineSegment* segp;
796  while ( iter != m_lsegments->end() )
797  {
798  segp = ( *iter );
799  if ( segp == seg )
800  {
801  wxASSERT_MSG( segp->GetArc() , _T( "this is not an arc segment." ) );
802  a2dArcSegment* cseg = ( a2dArcSegment* ) segp;
803  cseg->SetMidPoint( *( *iterp ), x, y );
804  break;
805  }
806  iterp = iter;
807  iter++;
808  }
809  SetPending( true );
810 }
811 
813 {
814  if ( !m_lworld.IsIdentity() )
815  {
816  m_lsegments->ConvertToLines();
817  a2dVertexList::iterator iter = m_lsegments->begin();
818  //first include transform
819  while ( iter != m_lsegments->end() )
820  {
821  a2dLineSegment* point = ( *iter );
822  m_lworld.TransformPoint( point->m_x, point->m_y, point->m_x, point->m_y );
823  iter++;
824  }
825 
826  }
828 }
829 
831 {
832  m_lsegments = points;
833 }
834 
835 bool a2dPolygonL::AdjustAfterChange( bool WXUNUSED( final ) )
836 {
837  return false;
838 }
839 
840 void a2dPolygonL::SetHandleToIndex( a2dPolyHandleL* handle, unsigned int index )
841 {
842  handle->SetNode( GetSegments()->item( index ) );
843  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
844  handle->SetNodeOrg( original->GetSegments()->item( index ) );
845 }
846 
847 void a2dPolygonL::OnEnterObject( a2dCanvasObjectMouseEvent& event )
848 {
849  if ( m_allowCrossAtVertex && (!m_flags.m_editingCopy || !m_flags.m_editable) )
850  {
851  m_crossAtVertex = true;
852  SetPending( true );
853  return;
854  }
855  event.Skip();
856 }
857 
858 void a2dPolygonL::OnLeaveObject( a2dCanvasObjectMouseEvent& event )
859 {
860  if ( m_allowCrossAtVertex && (!m_flags.m_editingCopy || !m_flags.m_editable) )
861  {
862  m_crossAtVertex = false;
863  SetPending( true );
864  return;
865  }
866  event.Skip();
867 }
868 
869 bool a2dPolygonL::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
870 {
871  if ( m_flags.m_editable )
872  {
873  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
874 
875  if ( editmode == 1 )
876  {
877  if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
878  {
879  m_flags.m_visiblechilds = true;
881 
882  //add properties and handles as children in order to edit the object.
883  a2dVertexList::iterator iter = m_lsegments->begin();
884  a2dVertexList::iterator iterorg = original->m_lsegments->begin();
885  a2dLineSegment* seg;
886  while ( iter != GetSegments()->end() )
887  {
888  seg = ( *iter );
889  //not inclusive matrix so relative to polygon
890  a2dPolyHandleL* handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->m_lsegments, wxT( "__index__" ) );
891  Append( handle );
892  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
893  handle->SetLayer( m_layer );
894 
895  if ( seg->GetArc() )
896  {
897  // todo split in line segments ( maybe under certain conditions of matrix not?? ).
898  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
899 
900  handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->m_lsegments, cseg->m_x2, cseg->m_y2, wxT( "__indexarc__" ) );
901  handle->SetArcHandle( true );
902  handle->SetLayer( m_layer );
903  Append( handle );
904  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
905  }
906  iter++;
907  iterorg++;
908  }
909 
910  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dPolyHandleL" ) );
911  m_flags.m_editingCopy = true;
912 
913  //calculate bbox's elase mouse events may take place when first idle event is not yet
914  //processed to do this calculation.
916  //stil set it pending to do the redraw ( in place )
917  SetPending( true );
918  }
919  return true;
920  }
921  else
922  {
923  PROPID_Allowrotation->SetPropertyToObject( this, true );
924  PROPID_Allowskew->SetPropertyToObject( this, true );
925 
926  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
927  }
928  }
929 
930  return false;
931 }
932 
933 void a2dPolygonL::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
934 {
936  {
937  event.Skip();
938  return;
939  }
940 
941  a2dIterC* ic = event.GetIterC();
942 
943  a2dPolyHandleL* seghandle;
944 
945  double xw, yw;
946  xw = event.GetX();
947  yw = event.GetY();
948 
949  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
950 
951  // this is the absolute matrix relative to the parent object, so with out this handle its
952  // m_lworld included.
953  // a2dAffineMatrix atWorld = ic->GetTransform();
954 
955 
956  if ( event.GetMouseEvent().Moving() )
957  {
958  if ( event.GetHow().IsStrokeHit() )
959  {
960  if ( !event.GetMouseEvent().AltDown() )
961  {
962  switch( event.GetHow().m_stroke2 )
963  {
964  case a2dHit::stroke2_edgehor:
965  case a2dHit::stroke2_edgevert:
966  case a2dHit::stroke2_edgeother:
967  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
968  break;
969  case a2dHit::stroke2_vertex:
970  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
971  break;
972  default:
973  break;
974  }
975  }
976  else
977  {
978  switch( event.GetHow().m_stroke2 )
979  {
980  case a2dHit::stroke2_edgehor:
981  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentHorizontal ) );
982  break;
983  case a2dHit::stroke2_edgevert:
984  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentVertical ) );
985  break;
986  case a2dHit::stroke2_edgeother:
987  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegment ) );
988  break;
989  case a2dHit::stroke2_vertex:
990  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireDeleteVertex ) );
991  break;
992  default:
993  break;
994  }
995  }
996  }
997  else
998  {
999  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HAND ) );
1000  event.Skip();
1001  }
1002  }
1003  else if ( event.GetMouseEvent().LeftDown() )
1004  {
1005  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
1006  if ( restrictEngine )
1007  restrictEngine->SetRestrictPoint( xw, yw );
1008 
1009  if ( event.GetHow().IsEdgeHit() )
1010  {
1011  wxUint16 editstyle = PROPID_Editstyle->GetPropertyValue( this );
1012  if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
1013  {
1014  a2dVertexList::iterator iterSeg = GetSegmentAtIndex( event.GetHow().m_index );
1015  a2dVertexList::iterator iterSegOrg = original->GetSegmentAtIndex( event.GetHow().m_index );
1016  a2dLineSegment* seg = *iterSeg;
1017  if ( event.GetMouseEvent().AltDown() )
1018  seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, m_lsegments, original->m_lsegments, wxT( "__segment__" ) );
1019  else
1020  seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, m_lsegments, original->m_lsegments, wxT( "__insert__" ) );
1021  seghandle->SetLayer( m_layer );
1022  Append( seghandle );
1023  seghandle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
1024  //canvas mouse events arrive without the polygon matrix included.
1025  a2dIterCU polygoncontext( *ic, this );
1026  a2dIterCU handlecontext( *ic, seghandle );
1027  seghandle->ProcessEvent( event );
1028  }
1029  }
1030  // If connected a move of a wire is weird, if not rewired.
1031  // Understand the wire edit copy is not connected (see edittool).
1032  else if ( ! original->IsConnected( false ) )
1033  event.Skip();
1034  }
1035  else
1036  event.Skip();
1037 }
1038 
1039 void a2dPolygonL::OnChar( wxKeyEvent& event )
1040 {
1041  if ( m_flags.m_editingCopy )
1042  {
1043  switch( event.GetKeyCode() )
1044  {
1045  case WXK_TAB:
1046  {
1047  wxUint16* editmode = PROPID_Editmode->GetPropertyValuePtr( this );
1048  if ( editmode )
1049  {
1050  ( *editmode )++;
1051  if ( ( *editmode ) > 1 ) ( *editmode ) = 0;
1052  ReStartEdit( ( *editmode ) );
1053  }
1054  break;
1055  }
1056  case WXK_DELETE:
1057  {
1058  if ( m_lsegments->size() <= 2 )
1059  {
1060  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
1061  break; // leaf at least one segment
1062  }
1063  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
1064  //first delete selected segments ( nodes maybe selcted, and those nodes maybe removed because of this.
1065  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
1066  {
1067  if ( m_lsegments->size() <= 2 )
1068  {
1069  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
1070  break; // leaf at least one segment
1071  }
1072  a2dCanvasObject* obj = *iter;
1073 
1074  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
1075 
1076  if ( handle && !handle->GetRelease( ) )
1077  {
1078  a2dVertexList::iterator iterpoly = handle->GetNode();
1079  a2dLineSegment* segment = *( iterpoly );
1080  if ( segment->GetBin() ) //selected?
1081  {
1082  iter = m_childobjects->GetNextAround( iter );
1083  a2dPolyHandleL* handle2 = wxDynamicCast( (*iter).Get(), a2dPolyHandleL );
1084  iter = m_childobjects->GetPreviousAround( iter );
1085  a2dLineSegment* segmentOrgNext = *( handle2->GetNodeOrg() );
1086  a2dLineSegment* segmentOrg = *( handle->GetNodeOrg() );
1087 
1088  double xn,yn;
1089  xn = (handle->GetPosX() + handle2->GetPosX())/2.0;
1090  yn = (handle->GetPosY() + handle2->GetPosY())/2.0;
1091  handle2->SetPosXY( xn, yn );
1092  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
1093  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, xn, yn, segmentOrgNext, false ) );
1094  a2dVertexList::iterator iterpolyNext = m_lsegments->GetNextAround( iterpoly );
1095  iterpoly = m_lsegments->erase( iterpoly );
1096  (*iterpolyNext)->m_x = xn; (*iterpolyNext)->m_y = yn;
1097  ReleaseChild( handle );
1098  }
1099  }
1100  }
1101 
1102  //now delete selected handles (only those which were not released above).
1103  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
1104  {
1105  a2dCanvasObject* obj = *iter;
1106 
1107  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
1108 
1109  if ( handle && !handle->GetRelease( ) && handle->GetSelected() )
1110  {
1111  a2dVertexList::iterator iterpoly = handle->GetNode();
1112  a2dLineSegment* segment = *( iterpoly );
1113  a2dVertexList::iterator iterorg = handle->GetNodeOrg();
1114  a2dLineSegment* segmentOrg = *( iterorg );
1115 
1116  if ( m_lsegments->size() <= 2 )
1117  {
1118  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
1119  break; // leaf at least one segment
1120  }
1121  else
1122  {
1123  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
1124  m_lsegments->erase( iterpoly );
1125  ReleaseChild( handle );
1126  }
1127  }
1128  }
1129  original->AdjustAfterChange( true );
1130  }
1131  break;
1132  default:
1133  event.Skip();
1134  }
1135  }
1136  else
1137  event.Skip();
1138 }
1139 
1140 void a2dPolygonL::SyncHandlesWithLineSegments()
1141 {
1142  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
1143  {
1144  a2dCanvasObject* obj = *iter;
1145 
1146  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
1147 
1148  if ( handle && !handle->GetRelease( ) )
1149  {
1150  a2dLineSegment* segment = *( handle->GetNode() );
1151  // handle a wxHandle position when its a arc segment
1152  if ( segment->GetArc() && handle->GetArcHandle() )
1153  {
1154  a2dArcSegment* cseg = ( a2dArcSegment* ) segment;
1155  // its an arc, so this handle can point to a midpoint
1156  handle->SetPosXyPoint( cseg->GetMidPoint() );
1157  }
1158  else
1159  handle->SetPosXY( segment->m_x, segment->m_y );
1160  }
1161  }
1162 }
1163 
1164 void a2dPolygonL::OnHandleEventEnter( a2dHandleMouseEvent& event )
1165 {
1166  a2dIterC* ic = event.GetIterC();
1167  //ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
1168  ic->GetDrawingPart()->PushCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_HandleEnter ) );
1169 }
1170 
1171 void a2dPolygonL::OnHandleEventLeave( a2dHandleMouseEvent& event )
1172 {
1173  a2dIterC* ic = event.GetIterC();
1174  //ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
1175  ic->GetDrawingPart()->PopCursor();
1176 }
1177 
1178 void a2dPolygonL::OnHandleEvent( a2dHandleMouseEvent& event )
1179 {
1180  a2dIterC* ic = event.GetIterC();
1181 
1182  if ( event.GetCanvasHandle()->GetRelease() )
1183  return;
1184 
1185  if ( m_flags.m_editingCopy )
1186  {
1187  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
1188  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
1189  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
1190 
1191  if ( editmode == 1 )
1192  {
1193  double xw, yw;
1194  xw = event.GetX();
1195  yw = event.GetY();
1196  a2dAffineMatrix atWorld = ic->GetTransform();
1197 
1198  //we need to get the matrix until the parent of the a2dPolyHandleL,
1199  // and not inclusif the handle itself.
1200  //and therefore apply inverted handle matrix.
1201  a2dAffineMatrix inverselocal = m_lworld;
1202  inverselocal.Invert();
1203 
1205 
1206  double xinternal, yinternal;
1207  inverse.TransformPoint( xw, yw, xinternal, yinternal );
1208 
1209  a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
1210  if ( !draghandle )
1211  return; //bad
1212  a2dPinPtr pin = draghandle->GetPin();
1213  a2dVertexList::iterator iter = draghandle->GetNode();
1214  a2dLineSegment* segment = *( iter );
1215  a2dLineSegment* segmentNext = *( m_lsegments->GetNextAround( iter ) );
1216  a2dVertexList::iterator iterorg = draghandle->GetNodeOrg();
1217  a2dLineSegment* segmentOrg = *( iterorg );
1218  a2dLineSegment* segmentNextOrg = *( original->m_lsegments->GetNextAround( iterorg ) );
1219 
1220  double xwi;
1221  double ywi;
1222  inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
1223  a2dAffineMatrix origworld = m_lworld;
1224 
1225  if ( draghandle->GetName() == wxT( "__index__" ) )
1226  {
1227  if( m_flags.m_snap )
1228  {
1229  if ( restrictEngine )
1230  restrictEngine->RestrictPoint( xwi, ywi );
1231  }
1232  if ( event.GetMouseEvent().AltDown() )
1233  {
1234  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireDeleteVertex ) );
1235  if ( event.GetMouseEvent().LeftDown() )
1236  {
1237  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
1238  //a2dToolContr* controller = wxStaticCast( PROPID_Controller->GetPropertyValue( this ).Get(), a2dToolContr );
1239  //controller->TriggerReStartEdit( 1 );
1240 
1241  double x, y;
1242  RemoveSegment( x, y, segment );
1243  ReleaseChild( draghandle );
1244 
1245  // the handle generated this event in LeftDown, But before LeftUp event the
1246  // restart is already done, getting rid of handle.
1247  // So do set context right here.
1248  ic->SetCorridorPathToParent();
1249  ic->GetDrawingPart()->PopCursor();
1250  }
1251  }
1252  else
1253  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireVertex ) );
1254 
1255  if ( event.GetMouseEvent().LeftUp() )
1256  {
1257  if ( draghandle->m_dragging )
1258  {
1259  draghandle->m_dragging = false;
1260  double x, y;
1261  x = segment->m_x; y = segment->m_y;
1262  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x, y, segmentOrg, false ) );
1263  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x, y, index );
1264  draghandle->SetPosXY( x, y );
1265  //Klaas (code not good, handles are used and removed at same time )
1266  //RemoveRedundantPoints( original );
1267  original->AdjustAfterChange( true );
1268 
1269 
1270  if ( pin )
1271  {
1272  original->SetAlgoSkip( true );
1273  SetAlgoSkip( true );
1274 
1275  double hitDistance = ic->GetHitMarginWorld();
1276 
1277  a2dPin* pinother = pin->GetPinClass()->GetConnectionGenerator()->
1278  SearchPinForFinishWire( ic->GetDrawingPart()->GetShowObject(), pin, NULL, hitDistance );
1279 
1280  if ( pinother && ! pin->IsConnectedTo( pinother ) )
1281  {
1282  m_root->GetCanvasCommandProcessor()->Submit( new a2dCommand_ConnectPins( pin, pinother ), true );
1283  }
1284 
1285  original->SetAlgoSkip( false );
1286  SetAlgoSkip( false );
1287  }
1288  }
1289  else
1290  draghandle->SetSelected( !draghandle->GetSelected() );
1291  }
1292  else if ( event.GetMouseEvent().Dragging() )
1293  {
1294  if ( pin && !draghandle->m_dragging && pin->FindNonWirePin() )
1295  pin->GetParent()->DisConnectAt( pin, true );
1296 
1297  //wxLogDebug( _("Dragging %d"), index);
1298  segment->m_x = xwi;
1299  segment->m_y = ywi;
1300  draghandle->m_dragging = true;
1301  SetPending( true );
1302  draghandle->SetPosXY( xwi, ywi );
1303  SetPosXYSegment( segment, xwi, ywi, false );
1304  AdjustAfterChange( false );
1305  }
1306  else if ( event.GetMouseEvent().Moving() )
1307  {
1308  }
1309  else
1310  event.Skip(); //maybe on the base class handles
1311  }
1312  else if ( draghandle->GetName() == wxT( "__indexarc__" ) )
1313  {
1314  if( m_flags.m_snap )
1315  {
1316  if ( restrictEngine )
1317  restrictEngine->RestrictPoint( xwi, ywi );
1318  }
1319  a2dArcSegment* csegment = ( a2dArcSegment* ) segment;
1320  if ( event.GetMouseEvent().LeftUp() )
1321  {
1322  double x, y;
1323  x = csegment->m_x2; y = csegment->m_y2;
1324  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveMidSegment( original, x, y, segmentOrg, false ) );
1325  //a2dDocviewGlobals->RecordF( this, wxT("movearcmidpoint %f %f %d"), x, y, index );
1326  draghandle->SetPosXY( x, y );
1327  //Klaas (code not good, handles are used and removed at same time )
1328  //RemoveRedundantPoints( original );
1329  original->AdjustAfterChange( true );
1330  }
1331  else if ( event.GetMouseEvent().Dragging() )
1332  {
1333  csegment->m_x2 = xwi; csegment->m_y2 = ywi;
1334  SetPending( true );
1335  //csegment->SetMidPoint( *prevsegment, xwi, ywi );
1336  //wxLogDebug( _("Dragging %d"), index);
1337  draghandle->SetPosXYRestrict( xwi, ywi );
1338  SyncHandlesWithLineSegments();
1339  AdjustAfterChange( false );
1340  }
1341  else
1342  event.Skip(); //maybe on the base class handles
1343  }
1344  else if ( draghandle->GetName() == wxT( "__insert__" ) )
1345  {
1346  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_WireSegmentInsert ) );
1347 
1348  // The index is the segment index. The index of the new point is 1 larger
1349  // than the segment index.
1350  if ( event.GetMouseEvent().LeftUp() && draghandle->m_dragging )
1351  {
1352  draghandle->m_dragging = false;
1353  double x, y;
1354  GetPosXYSegment( segmentNext, x, y, false );
1355  m_root->GetCommandProcessor()->Submit( new a2dCommand_AddPoint( original, x, y, segmentNextOrg, false ) );
1356  // !!!!???? how to do this ????!!!!
1357  // a2dDocviewGlobals->RecordF( this, wxT("addpoint %f %f %d"), x, y, index+1 );
1358  draghandle->SetPosXY( x, y );
1359  draghandle->SetName( wxT( "__index__" ) );
1360  iter = m_lsegments->GetNextAround( iter );
1361  iterorg = original->m_lsegments->GetNextAround( iterorg );
1362  draghandle->SetNode( iter );
1363  draghandle->SetNodeOrg( iterorg );
1364 
1365  original->AdjustAfterChange( true );
1366  segment->m_bin = false;
1367  }
1368  else if ( event.GetMouseEvent().LeftUp() )
1369  {
1370  segment->m_bin = !segment->m_bin; //use bin for select
1371  SetPending( true );
1372  draghandle->m_dragging = false;
1373  draghandle->SetRelease( true );
1374  original->AdjustAfterChange( true );
1375  }
1376  else if ( event.GetMouseEvent().LeftDown() )
1377  {
1378  draghandle->m_dragging = false;
1379  }
1380  else if ( event.GetMouseEvent().Dragging() && !draghandle->m_dragging )
1381  {
1382  draghandle->m_dragging = true;
1383  draghandle->SetPosXYRestrict( xwi, ywi );
1384  AddPoint( xwi, ywi, segmentNext, false );
1385  AdjustAfterChange( false );
1386  }
1387  else if ( event.GetMouseEvent().Dragging() )
1388  {
1389  draghandle->SetPosXYRestrict( xwi, ywi );
1390  SetPosXYSegment( segmentNext, xwi, ywi , false );
1391  AdjustAfterChange( false );
1392  }
1393  else
1394  event.Skip(); //maybe on the base class handles
1395  }
1396  else if ( draghandle->GetName() == wxT( "__segment__" ) )
1397  {
1398  if ( event.GetMouseEvent().LeftUp() )
1399  {
1400  if ( !draghandle->m_dragging )
1401  {
1402  segment->m_bin = !segment->m_bin; //use bin for select
1403  SetPending( true );
1404  }
1405  else
1406  {
1407  segment->m_bin = false;
1408  draghandle->m_dragging = false;
1409 
1410  if( m_flags.m_snap )
1411  {
1412  double xi_h = a2dPolyHandleL::PROPID_tmpXIH->GetPropertyValue( draghandle );
1413  double yi_h = a2dPolyHandleL::PROPID_tmpYIH->GetPropertyValue( draghandle );
1414  double xi_v1 = a2dPolyHandleL::PROPID_tmpXIV1->GetPropertyValue( draghandle );
1415  double yi_v1 = a2dPolyHandleL::PROPID_tmpYIV1->GetPropertyValue( draghandle );
1416  double xi_v2 = a2dPolyHandleL::PROPID_tmpXIV2->GetPropertyValue( draghandle );
1417  double yi_v2 = a2dPolyHandleL::PROPID_tmpYIV2->GetPropertyValue( draghandle );
1418  xwi = segment->m_x + xi_v1 - xi_h;
1419  ywi = segment->m_y + yi_v1 - yi_h;
1420  }
1421  draghandle->SetPosXY( xwi, ywi );
1422 
1423  double x1 = segment->m_x;
1424  double y1 = segment->m_y;
1425  double x2 = segmentNext->m_x;
1426  double y2 = segmentNext->m_y;
1427 
1428  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x1, y1, segmentOrg, false ) );
1429  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x2, y2, segmentNextOrg, false ) );
1430 
1431  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x1, y1, index );
1432  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x2, y2, index+1 );
1433  }
1434  //Klaas (code not good, handles are used and removed at same time )
1435  //RemoveRedundantPoints( original );
1436  //
1437  SyncHandlesWithLineSegments();
1438 
1439 
1440  // handles called "__segment__" are temporary handles, can be removed after drag
1441  m_childobjects->Release( a2dCanvasOFlags::ALL, wxT( "a2dPolyHandleL" ), NULL, wxT( "__segment__" ), false );
1442  original->AdjustAfterChange( true );
1443  }
1444  else if ( event.GetMouseEvent().LeftDown() )
1445  {
1446  // set the initial handle coordinates
1447  a2dPolyHandleL::PROPID_tmpXIH->SetPropertyToObject( draghandle, xwi );
1448  a2dPolyHandleL::PROPID_tmpYIH->SetPropertyToObject( draghandle, ywi );
1449  // set the initial vertex coordinates
1450  double x, y;
1451  x = segment->m_x;
1452  y = segment->m_y;
1453  a2dPolyHandleL::PROPID_tmpXIV1->SetPropertyToObject( draghandle, x );
1454  a2dPolyHandleL::PROPID_tmpYIV1->SetPropertyToObject( draghandle, y );
1455  x = segmentNext->m_x;
1456  y = segmentNext->m_y;
1457  a2dPolyHandleL::PROPID_tmpXIV2->SetPropertyToObject( draghandle, x );
1458  a2dPolyHandleL::PROPID_tmpYIV2->SetPropertyToObject( draghandle, y );
1459  }
1460  else if ( event.GetMouseEvent().Dragging() )
1461  {
1462  draghandle->m_dragging = true;
1463 
1464  double xi_h = a2dPolyHandleL::PROPID_tmpXIH->GetPropertyValue( draghandle );
1465  double yi_h = a2dPolyHandleL::PROPID_tmpYIH->GetPropertyValue( draghandle );
1466  double xi_v1 = a2dPolyHandleL::PROPID_tmpXIV1->GetPropertyValue( draghandle );
1467  double yi_v1 = a2dPolyHandleL::PROPID_tmpYIV1->GetPropertyValue( draghandle );
1468  double xi_v2 = a2dPolyHandleL::PROPID_tmpXIV2->GetPropertyValue( draghandle );
1469  double yi_v2 = a2dPolyHandleL::PROPID_tmpYIV2->GetPropertyValue( draghandle );
1470 
1471  //wxASSERT( xi_h && yi_h && xi_v1 && yi_v1 && xi_v2 && yi_v2 );
1472 
1473  if( m_flags.m_snap )
1474  {
1475  // snap vertex 1 of segment.
1476  double x, y, dx, dy;
1477 
1478  dx = xi_v1 - xi_h;
1479  dy = yi_v1 - yi_h;
1480  x = xwi + dx;
1481  y = ywi + dy;
1482  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
1483  if ( restrictEngine )
1484  restrictEngine->RestrictPoint( x, y );
1485  xwi = x - dx;
1486  ywi = y - dy;
1487  }
1488  draghandle->SetPosXY( xwi, ywi );
1489  double x1 = xi_v1 - xi_h + xwi;
1490  double y1 = yi_v1 - yi_h + ywi;
1491  double x2 = xi_v2 - xi_h + xwi;
1492  double y2 = yi_v2 - yi_h + ywi;
1493 
1494  segment->m_x = x1;
1495  segment->m_y = y1;
1496  segmentNext->m_x = x2;
1497  segmentNext->m_y = y2;
1498 
1499  SetPending( true );
1500  AdjustAfterChange( false );
1501  }
1502  else if ( event.GetMouseEvent().Moving() )
1503  {
1504  //ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentHorizontal ) );
1505  //ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegmentVertical ) );
1506  ic->GetDrawingPart()->SetCursor( a2dCanvasGlobals->GetCursor( a2dCURSOR_EditWireSegment ) );
1507  }
1508  else
1509  event.Skip(); //maybe on the base class handles
1510  }
1511  else
1512  event.Skip(); //maybe the base class handles
1513  }
1514  else
1515  event.Skip();
1516  }
1517  else
1518  {
1519  event.Skip();
1520  }
1521 }
1522 
1523 a2dBoundingBox a2dPolygonL::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
1524 {
1525  a2dBoundingBox bbox;
1526  if ( m_spline )
1527  {
1528  a2dVertexList* lpoints = new a2dVertexList();
1529 
1530  *lpoints = *m_lsegments;
1531  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
1532  bbox = lpoints->GetBbox();
1533  delete lpoints;
1534  }
1535  else
1536  bbox = m_lsegments->GetBbox();
1537 
1538  if ( m_contourwidth > 0 )
1539  bbox.Enlarge( m_contourwidth / 2 );
1540 
1541  return bbox;
1542 }
1543 
1544 bool a2dPolygonL::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
1545 {
1546  if ( !m_bbox.GetValid() )
1547  {
1548  if ( m_spline )
1549  {
1550  a2dVertexList* lpoints = new a2dVertexList();
1551 
1552  *lpoints = *m_lsegments;
1553  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
1554  m_bbox = lpoints->GetBbox( m_lworld );
1555  delete lpoints;
1556  }
1557 
1559  bboxs.MapBbox( m_lworld );
1560  m_bbox.Expand( bboxs );
1561 
1562  if ( m_flags.m_editingCopy && m_spline )
1563  {
1564  m_spline = false;
1566  bboxs.MapBbox( m_lworld );
1567  m_bbox.Expand( bboxs );
1568  m_spline = true;
1569  }
1570  return true;
1571  }
1572  return false;
1573 }
1574 
1575 void a2dPolygonL::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
1576 {
1577  if ( m_contourwidth )
1578  {
1579  a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth / 2, a2dPATH_END_ROUND, true );
1580  ic.GetDrawer2D()->DrawPolygon( contourpoints, m_spline );
1581  delete contourpoints;
1582  }
1583  else
1584  ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE );
1585 
1586  if ( m_crossAtVertex )
1587  {
1588  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
1589  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
1590  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetHandle()->GetFill() );
1591  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetHandle()->GetStroke() );
1592 
1593  double x, y;
1596 
1597  a2dVertexList::iterator iter = m_lsegments->begin();
1598  a2dLineSegment* seg;
1599  while ( iter != m_lsegments->end() )
1600  {
1601  seg = ( *iter );
1602  x = seg->m_x;
1603  y = seg->m_y;
1604  double xd, yd;
1605  matrix.TransformPoint( x, y, xd, yd );
1606 
1607  ic.GetDrawer2D()->DrawCircle( xd, yd, a2dCrossAtVertexSize );
1608  iter++;
1609  }
1610  ic.GetDrawer2D()->PopTransform();
1611  ic.GetDrawer2D()->SetDrawerStroke( current );
1612  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
1613  }
1614 
1615  if ( m_flags.m_editingCopy )
1616  {
1619  double x, y, w, h;
1620  x = untrans.GetMinX();
1621  y = untrans.GetMinY();
1622  w = untrans.GetWidth();
1623  h = untrans.GetHeight();
1624 
1625  if ( m_spline )
1626  ic.GetDrawer2D()->DrawPolygon( m_lsegments, false, wxWINDING_RULE );
1627 
1628  a2dSmrtPtr<a2dRect> around = new a2dRect( x, y, w, h );
1629  around->SetIgnoreSetpending();
1630  around->SetRoot( m_root, false );
1631  around->Update( updatemask_force );
1632  around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
1633  around->SetFill( *a2dTRANSPARENT_FILL );
1634  around->Render( ic, _ON );
1635 
1636  double xp, yp;
1637  a2dVertexList::iterator iter = m_lsegments->begin();
1638  a2dLineSegment* seg;
1639  while ( iter != m_lsegments->end() )
1640  {
1641  seg = ( *iter );
1642  if ( seg->GetBin() ) //selected?
1643  {
1644  x = seg->m_x;
1645  y = seg->m_y;
1646  a2dLineSegment* nextseg = *( m_lsegments->GetNextAround( iter ) );
1647  xp = nextseg->m_x;
1648  yp = nextseg->m_y;
1649 
1650  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetSelectFill() );
1651  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetSelectStroke() );
1652  ic.GetDrawer2D()->DrawLine( x, y, xp, yp );
1653  }
1654  iter++;
1655  }
1656 
1658  }
1659 }
1660 
1661 #if wxART2D_USE_CVGIO
1662 void a2dPolygonL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
1663 {
1664  a2dCanvasObject::DoSave( parent, out, xmlparts, towrite );
1665  if ( xmlparts == a2dXmlSer_attrib )
1666  {
1667  if ( m_spline )
1668  {
1669  out.WriteAttribute( wxT( "spline" ), m_spline );
1670  }
1671 
1672  out.WriteAttribute( wxT( "points" ), m_lsegments->size() );
1673  out.WriteAttribute( wxT( "contourwidth" ), m_contourwidth * out.GetScale() );
1674  }
1675  else
1676  {
1677  unsigned int i = 0;
1678  forEachIn( a2dVertexList, m_lsegments )
1679  {
1680  if ( i % 6 == 0 )
1681  out.WriteNewLine();
1682  a2dLineSegment* seg = *iter;
1683  out.WriteStartElementAttributes( wxT( "xy" ) );
1684  out.WriteAttribute( wxT( "x" ), seg->m_x * out.GetScale() );
1685  out.WriteAttribute( wxT( "y" ), seg->m_y * out.GetScale() );
1686 
1687  if ( seg->GetArc() )
1688  {
1689  a2dArcSegment* arc = ( a2dArcSegment* ) seg;
1690  out.WriteAttribute( wxT( "xm" ), arc->m_x2 * out.GetScale() );
1691  out.WriteAttribute( wxT( "ym" ), arc->m_y2 * out.GetScale() );
1692  }
1693 
1694  out.WriteEndAttributes( true );
1695  i++;
1696  }
1697  }
1698 }
1699 
1700 void a2dPolygonL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
1701 {
1702  a2dCanvasObject::DoLoad( parent, parser, xmlparts );
1703  if ( xmlparts == a2dXmlSer_attrib )
1704  {
1705  m_spline = parser.GetAttributeValueBool( wxT( "spline" ), false );
1706  m_contourwidth = parser.GetAttributeValueDouble( wxT( "contourwidth" ), 0 ) * parser.GetScale() ;
1707  }
1708  else
1709  {
1710  while( parser.GetTagName() == wxT( "xy" ) )
1711  {
1712  double x = parser.GetAttributeValueDouble( wxT( "x" ) ) * parser.GetScale() ;
1713  double y = parser.GetAttributeValueDouble( wxT( "y" ) ) * parser.GetScale() ;
1714 
1715  a2dLineSegment* seg;
1716  if ( parser.HasAttribute( wxT( "xm" ) ) )
1717  {
1718  double xm = parser.GetAttributeValueDouble( wxT( "xm" ) ) * parser.GetScale() ;
1719  double ym = parser.GetAttributeValueDouble( wxT( "ym" ) ) * parser.GetScale() ;
1720 
1721  seg = new a2dArcSegment( x, y, xm, ym );
1722  }
1723  else
1724  seg = new a2dLineSegment( x, y );
1725 
1726  m_lsegments->push_back( seg );
1727 
1728  parser.Next();
1729  parser.Require( END_TAG, wxT( "xy" ) );
1730  parser.Next();
1731  }
1732  }
1733 }
1734 #endif //wxART2D_USE_CVGIO
1735 
1737 {
1738  double xh, yh;
1739  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, xh, yh );
1740 
1741  a2dPoint2D P = a2dPoint2D( xh, yh );
1742  double pw = ic.GetWorldStrokeExtend();
1743  double margin = ic.GetTransformedHitMargin();
1744 
1745  hitEvent.m_how = PointInPolygon( P, pw + margin );
1746 
1747  return hitEvent.m_how.IsHit();
1748 }
1749 
1750 a2dHit a2dPolygonL::PointInPolygon( const a2dPoint2D& P, double marge )
1751 {
1752  a2dVertexList* rlist;
1753  if ( m_spline )
1754  {
1755 
1756  a2dVertexList* lpoints = new a2dVertexList();
1757  *lpoints = *m_lsegments;
1758  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
1759  rlist = lpoints;
1760  }
1761  else
1762  rlist = m_lsegments;
1763 
1764  a2dHit result = rlist->HitTestPolygon( P, marge );
1765 
1766  if ( m_spline )
1767  delete rlist;
1768 
1769  return result;
1770 }
1771 
1772 //----------------------------------------------------------------------------
1773 // a2dPolylineL
1774 //----------------------------------------------------------------------------
1775 
1776 BEGIN_EVENT_TABLE( a2dPolylineL, a2dPolygonL )
1777  EVT_CHAR( a2dPolylineL::OnChar )
1778 END_EVENT_TABLE()
1779 
1780 bool a2dPolylineL::m_generatePins = false;
1781 
1783  : a2dPolygonL()
1784 {
1785  m_xscale = m_yscale = 1;
1786  m_pathtype = a2dPATH_END_SQAURE;
1787  m_flags.m_generatePins = m_generatePins;
1788  m_flags.m_filled = false;
1789 }
1790 
1791 a2dPolylineL::a2dPolylineL( a2dVertexListPtr points, bool spline )
1792  : a2dPolygonL( points, spline )
1793 {
1794  m_xscale = m_yscale = 1;
1795  m_pathtype = a2dPATH_END_SQAURE;
1796  m_flags.m_generatePins = m_generatePins;
1797  m_flags.m_filled = false;
1798 }
1799 
1800 a2dPolylineL::a2dPolylineL( const a2dPolylineL& other, CloneOptions options, a2dRefMap* refs )
1801  : a2dPolygonL( other, options, refs )
1802 {
1803  //if ( options & clone_members )
1804  //{
1805  m_begin = NULL;
1806  m_end = NULL;
1807  if ( other.m_begin )
1808  m_begin = other.m_begin->TClone( options );
1809  if ( other.m_end )
1810  m_end = other.m_end->TClone( options );
1811  //}
1812  //else
1813  //{
1814  //m_begin = other.m_begin;
1815  //m_end = other.m_end;
1816  //}
1817  m_xscale = other.m_xscale;
1818  m_yscale = other.m_yscale;
1819  m_pathtype = other.m_pathtype;
1820  m_flags.m_generatePins = other.m_generatePins;
1821  m_flags.m_filled = other.m_flags.m_filled;
1822 #if defined(_DEBUG) && defined (SMART_POINTER_DEBUG)
1823  //klion: it is because the CurrentSmartPointerOwner can change in Clone ( )
1824  CurrentSmartPointerOwner = this;
1825 #endif
1826 }
1827 
1828 a2dPolylineL::~a2dPolylineL()
1829 {
1830 }
1831 
1833 {
1834  SetPending( true );
1835  m_begin = begin;
1836  if ( m_begin && m_root )
1837  m_begin->SetRoot( m_root );
1838 }
1839 
1841 {
1842  SetPending( true );
1843  m_end = end;
1844  if ( m_end && m_root )
1845  m_end->SetRoot( m_root );
1846 }
1847 
1849 {
1850  return new a2dPolylineL( *this, options, refs );
1851 }
1852 
1853 a2dVertexList* a2dPolylineL::GetAsVertexList( bool& returnIsPolygon ) const
1854 {
1855  if ( m_contourwidth )
1856  {
1857  a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth / 2, m_pathtype );
1858  if ( !returnIsPolygon )
1859  contourpoints->push_back( contourpoints->front()->Clone() );
1860  return contourpoints;
1861  }
1862  else
1863  {
1864  returnIsPolygon = false;
1865  return new a2dVertexList( *(m_lsegments.Get()) );
1866  }
1867 }
1868 
1870 {
1871  a2dAffineMatrix pworld;
1872  if ( transform )
1873  pworld = m_lworld;
1874 
1875  a2dVpath* segments = NULL;
1876 
1877  if ( m_contourwidth )
1878  {
1879  if ( a2dGlobals->GetRoundFactor() == 0 && m_pathtype == a2dPATH_END_ROUND )
1880  {
1881  segments = new a2dVpath();
1882 
1883  a2dVertexList contourpoints = *m_lsegments;
1884  contourpoints.ConvertToLines();
1885 
1886  a2dLineSegment* segprev = NULL;
1887  a2dLineSegment* seg = NULL;
1888  a2dPoint2D first;
1889  a2dPoint2D second;
1890  a2dPoint2D offsetpointleft;
1891  a2dPoint2D offsetpointright;
1892 
1893  a2dVertexList::iterator iter = contourpoints.begin();
1894  while( iter != contourpoints.end() )
1895  {
1896  a2dLineSegment* seg = *iter;
1897  seg = ( *iter );
1898 
1899  if ( segprev )
1900  {
1901  first = a2dPoint2D( segprev->m_x, segprev->m_y );
1902  second = a2dPoint2D( seg->m_x, seg->m_y );
1903  offsetpointleft = first;
1904  offsetpointright = first;
1905  a2dLine line1( first, second );
1906  line1.CalculateLineParameters();
1907  line1.Virtual_Point( offsetpointleft, m_contourwidth / 2 );
1908  line1.Virtual_Point( offsetpointright, -m_contourwidth / 2 );
1909 
1910  a2dVpathSegment* segv = new a2dVpathSegment( offsetpointright.m_x, offsetpointright.m_y, a2dPATHSEG_MOVETO );
1911  segments->Add( segv );
1912 
1913  a2dLine lineoffset( offsetpointright, offsetpointleft );
1914  lineoffset.CalculateLineParameters();
1915  a2dPoint2D offsetpointfirst;
1916  offsetpointfirst = first;
1917  lineoffset.Virtual_Point( offsetpointfirst, m_contourwidth / 2 );
1918  segments->Add( new a2dVpathArcSegment( offsetpointleft.m_x, offsetpointleft.m_y,
1919  offsetpointfirst.m_x, offsetpointfirst.m_y,
1921 
1922  offsetpointright = second;
1923  line1.Virtual_Point( offsetpointright, -m_contourwidth / 2 );
1924  offsetpointleft = second;
1925  line1.Virtual_Point( offsetpointleft, m_contourwidth / 2 );
1926 
1927  segv = new a2dVpathSegment( offsetpointleft.m_x, offsetpointleft.m_y, a2dPATHSEG_LINETO, a2dPATHSEG_END_OPEN );
1928  segments->Add( segv );
1929 
1930  a2dLine lineoffset2( offsetpointleft, offsetpointright );
1931  lineoffset2.CalculateLineParameters();
1932  a2dPoint2D offsetpointend;
1933  offsetpointend = second;
1934  lineoffset2.Virtual_Point( offsetpointend, m_contourwidth / 2 );
1935  segments->Add( new a2dVpathArcSegment( offsetpointright.m_x, offsetpointright.m_y,
1936  offsetpointend.m_x, offsetpointend.m_y,
1938 
1939  segv = new a2dVpathSegment( offsetpointright.m_x, offsetpointright.m_y, a2dPATHSEG_LINETO, a2dPATHSEG_END_CLOSED );
1940  segments->Add( segv );
1941  }
1942  iter++;
1943  segprev = seg;
1944  }
1945  }
1946  else
1947  {
1948  segments = new a2dVpath( *m_lsegments, true );
1949  segments->Contour( m_contourwidth / 2, m_pathtype );
1950  }
1951  }
1952  else
1953  {
1954  a2dVertexList contourpoints = *m_lsegments;
1955  segments = new a2dVpath( contourpoints, true, false );
1956  }
1957  if ( transform )
1958  segments->Transform( pworld );
1959 
1960  a2dVectorPath* canpath = new a2dVectorPath( segments );
1961  canpath->SetRoot( m_root );
1962  canpath->SetStroke( this->GetStroke() );
1963  canpath->SetFill( this->GetFill() );
1964  canpath->SetLayer( m_layer );
1965  a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
1966  canpathlist->push_back( canpath );
1967  return canpathlist;
1968 }
1969 
1970 a2dCanvasObjectList* a2dPolylineL::GetAsLinesArcs( bool transform )
1971 {
1972  a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
1973 
1974  double xp = m_lsegments->front()->m_x;
1975  double yp = m_lsegments->front()->m_y;
1976  if ( transform )
1977  m_lworld.TransformPoint( xp, yp, xp, yp );
1978  a2dCanvasObject* obj;
1979  a2dVertexList::iterator iter = m_lsegments->begin();
1980  iter++;
1981  while( iter != m_lsegments->end() )
1982  {
1983  double x, y, xm, ym;
1984  a2dLineSegment* seg = *iter;
1985  x = seg->m_x; y = seg->m_y;
1986  if ( transform )
1987  m_lworld.TransformPoint( x, y, x, y );
1988  if ( seg->GetArc() )
1989  {
1990  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
1991  xm = cseg->m_x2; ym = cseg->m_y2;
1992  if ( transform )
1993  m_lworld.TransformPoint( xm, ym, xm, ym );
1994  a2dArc* arc = new a2dArc();
1995  arc->SetChord( true );
1996  obj = arc;
1997  arc->Set( xp, yp, xm, ym, x, y );
1998  linesAnArcs->push_back( arc );
1999  }
2000  else
2001  {
2002  a2dSLine* line = new a2dSLine( xp, yp, x, y );
2003  obj = line;
2004  linesAnArcs->push_back( line );
2005  }
2006 
2007  obj->SetStroke( this->GetStroke() );
2008  obj->SetFill( this->GetFill() );
2009  obj->SetLayer( m_layer );
2010  obj->SetContourWidth( GetContourWidth() );
2011  obj->SetRoot( m_root, false );
2012 
2013  xp = x;
2014  yp = y;
2015  ++iter;
2016  }
2017 
2018  return linesAnArcs;
2019 }
2020 
2021 
2023 {
2024  a2dVertexList::iterator iterp = m_lsegments->end();
2025  a2dVertexList::iterator iterpp = m_lsegments->end();
2026  a2dVertexList::iterator iter = m_lsegments->begin();
2027 
2028  int inode;
2029 
2030  // remove equal points
2031  iter = m_lsegments->begin();
2032  inode = 0;
2033  if( iter != m_lsegments->end() )
2034  {
2035  iterp = iter++;
2036  inode++;
2037  }
2038  while ( iter != m_lsegments->end() )
2039  {
2040  a2dLineSegment* line1 = *iterp;
2041  a2dLineSegment* line2 = *iter;
2042  if( line1->GetPoint() == line2->GetPoint() && !line1->GetArc() ) //this is arc save on line2
2043  {
2044  if( sendCommandsTo )
2045  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode ) );
2046  m_lsegments->erase( iterp );
2047  }
2048  else
2049  {
2050  inode++;
2051  }
2052 
2053  iterp = iter++;
2054  }
2055 
2056  //remove points on same x/y
2057  iter = m_lsegments->begin();
2058  inode = 0;
2059  if( iter != m_lsegments->end() )
2060  {
2061  iterp = iter++;
2062  inode++;
2063  }
2064  if( iter != m_lsegments->end() )
2065  {
2066  iterpp = iterp;
2067  iterp = iter++;
2068  inode++;
2069  }
2070  while ( iter != m_lsegments->end() )
2071  {
2072  a2dLineSegment* point0 = *iterpp;
2073  a2dLineSegment* point1 = *iterp;
2074  a2dLineSegment* point2 = *iter;
2075 
2076  if ( !point0->GetArc() && !point1->GetArc() &&
2077  ( ( point1->GetPoint().m_x == point0->GetPoint().m_x && point1->GetPoint().m_x == point2->GetPoint().m_x ) ||
2078  ( point1->GetPoint().m_y == point0->GetPoint().m_y && point1->GetPoint().m_y == point2->GetPoint().m_y )
2079  )
2080  )
2081  {
2082  if( sendCommandsTo )
2083  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode -1 ) );
2084  m_lsegments->erase( iterp );
2085  }
2086  else
2087  {
2088  inode++;
2089  iterpp = iterp;
2090  }
2091  iterp = iter++;
2092  }
2093 
2094  /*
2095  // remove 180 deg points
2096  iter = m_lsegments->begin();
2097  inode = 0;
2098  if( iter != m_lsegments->end() )
2099  {
2100  iterp = iter++;
2101  inode++;
2102  }
2103  if( iter != m_lsegments->end() )
2104  {
2105  iterpp = iterp;
2106  iterp = iter++;
2107  inode++;
2108  }
2109  while ( iter != m_lsegments->end() )
2110  {
2111  a2dLineSegment* point0 = *iterpp;
2112  a2dLineSegment* point1 = *iterp;
2113  a2dLineSegment* point2 = *iter;
2114 
2115  double dx10 = point1->m_x - point0->m_x;
2116  double dy10 = point1->m_y - point0->m_y;
2117  double dx21 = point2->m_x - point1->m_x;
2118  double dy21 = point2->m_y - point1->m_y;
2119 
2120  if( !point0->GetArc() && !point1->GetArc() && dx10* dy21 - dx21* dy10 == 0 )
2121  {
2122  if( sendCommandsTo )
2123  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode - 1 ) );
2124  m_lsegments->erase( iterp );
2125  }
2126  else
2127  {
2128  inode++;
2129  iterpp = iterp;
2130  }
2131  iterp = iter++;
2132  }
2133  */
2134 }
2135 
2136 void a2dPolylineL::Remove180DegPoints( a2dCanvasObject* sendCommandsTo, bool removeZeroFirst )
2137 {
2138  a2dVertexList::iterator iterp = m_lsegments->end();
2139  a2dVertexList::iterator iterpp = m_lsegments->end();
2140  a2dVertexList::iterator iter = m_lsegments->begin();
2141  int inode;
2142 
2143  if ( removeZeroFirst )
2144  {
2145  // remove equal points
2146  iter = m_lsegments->begin();
2147  inode = 0;
2148  if( iter != m_lsegments->end() )
2149  {
2150  iterp = iter++;
2151  inode++;
2152  }
2153  while ( iter != m_lsegments->end() )
2154  {
2155  a2dLineSegment* line1 = *iterp;
2156  a2dLineSegment* line2 = *iter;
2157  if( line1->GetPoint() == line2->GetPoint() && !line1->GetArc() ) //this is arc save on line2
2158  {
2159  if( sendCommandsTo )
2160  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode ) );
2161  m_lsegments->erase( iterp );
2162  }
2163  else
2164  {
2165  inode++;
2166  }
2167 
2168  iterp = iter++;
2169  }
2170  }
2171 
2172  // remove 180 deg points
2173  iter = m_lsegments->begin();
2174  inode = 0;
2175  if( iter != m_lsegments->end() )
2176  {
2177  iterp = iter++;
2178  inode++;
2179  }
2180  if( iter != m_lsegments->end() )
2181  {
2182  iterpp = iterp;
2183  iterp = iter++;
2184  inode++;
2185  }
2186  while ( iter != m_lsegments->end() )
2187  {
2188  a2dLineSegment* point0 = *iterpp;
2189  a2dLineSegment* point1 = *iterp;
2190  a2dLineSegment* point2 = *iter;
2191 
2192  double dx10 = point1->m_x - point0->m_x;
2193  double dy10 = point1->m_y - point0->m_y;
2194  double dx21 = point2->m_x - point1->m_x;
2195  double dy21 = point2->m_y - point1->m_y;
2196 
2197  double angle = atan2( dy10, dx10 ) - atan2( dy21, dx21 );
2198 
2199  if( point1->Length( *point0 ) > 0 && point2->Length( *point1 ) > 0 &&
2200  !point0->GetArc() && !point1->GetArc() && ( angle == wxPI || angle == -wxPI ) )
2201  {
2202  if( sendCommandsTo )
2203  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( sendCommandsTo, inode - 1 ) );
2204  m_lsegments->erase( iterp );
2205  }
2206  else
2207  {
2208  inode++;
2209  iterpp = iterp;
2210  }
2211  iterp = iter++;
2212  }
2213 }
2214 
2215 a2dBoundingBox a2dPolylineL::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
2216 {
2217  a2dBoundingBox bbox;
2218  if ( m_spline )
2219  {
2220  a2dVertexList* lpoints = new a2dVertexList();
2221 
2222  *lpoints = *m_lsegments;
2223  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
2224  bbox = lpoints->GetBbox();
2225  delete lpoints;
2226  }
2227  else
2228  bbox = m_lsegments->GetBbox();
2229 
2230  if ( m_contourwidth > 0 )
2231  bbox.Enlarge( m_contourwidth / 2 );
2232 
2233  if ( m_begin )
2234  {
2235  a2dVertexList::iterator iter = m_lsegments->begin();
2236  a2dPoint2D point1 = GetPosXY();
2237  a2dPoint2D point2 = GetPosXY();
2238  if ( iter != m_lsegments->end() )
2239  {
2240  point1 = ( *iter )->GetPoint();
2241  iter++;
2242  if ( iter != m_lsegments->end() )
2243  point2 = ( *iter )->GetPoint();
2244  else
2245  point2 = point1;
2246  }
2247 
2248  double dx, dy;
2249  dx = point2.m_x - point1.m_x;
2250  dy = point2.m_y - point1.m_y;
2251  double ang1;
2252  if ( !dx && !dy )
2253  ang1 = 0;
2254  else
2255  ang1 = wxRadToDeg( atan2( dy, dx ) );
2256 
2257  a2dAffineMatrix lworld;
2258  //clockwise rotation so minus
2259  lworld.Scale( m_xscale, m_yscale, 0, 0 );
2260  lworld.Rotate( -ang1 );
2261  lworld.Translate( point1.m_x, point1.m_y );
2262 
2263  bbox.Expand( m_begin->GetMappedBbox( lworld ) );
2264 
2265  }
2266 
2267  if ( m_end )
2268  {
2269  double dx = 0;
2270  double dy = 0;
2271  a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
2272  a2dPoint2D point1 = GetPosXY();
2273  a2dPoint2D point2 = GetPosXY();
2274  if ( iter != m_lsegments->rend() )
2275  {
2276  point1 = ( *iter )->GetPoint();
2277  while ( !dx && !dy && iter != m_lsegments->rend() )
2278  {
2279  point1 = ( *iter )->GetPoint();
2280  iter++;
2281  if ( iter != m_lsegments->rend() )
2282  point2 = ( *iter )->GetPoint();
2283  else
2284  point2 = point1;
2285  dx = point2.m_x - point1.m_x;
2286  dy = point2.m_y - point1.m_y;
2287  }
2288  }
2289 
2290  double ang2;
2291  if ( !dx && !dy )
2292  ang2 = 0;
2293  else
2294  ang2 = wxRadToDeg( atan2( dy, dx ) );
2295 
2296  a2dAffineMatrix tworld;
2297  //clockwise rotation so minus
2298  tworld.Scale( m_xscale, m_yscale, 0, 0 );
2299  tworld.Rotate( -ang2 );
2300  tworld.Translate( point1.m_x, point1.m_y );
2301 
2302  bbox.Expand( m_end->GetMappedBbox( tworld ) );
2303 
2304  }
2305 
2306  return bbox;
2307 }
2308 
2309 bool a2dPolylineL::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
2310 {
2311  bool calc = false;
2312  if ( m_begin )
2313  {
2314  calc = m_begin->Update( mode );
2315  }
2316  if ( m_end )
2317  {
2318  calc = m_end->Update( mode );
2319  }
2320 
2321  if ( !m_bbox.GetValid() || calc )
2322  {
2323  // first convert then transform is better here, else sometimes missing things.
2324  if ( m_spline )
2325  {
2326  a2dVertexList* lpoints = new a2dVertexList();
2327 
2328  *lpoints = *m_lsegments;
2329  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
2330  m_bbox = lpoints->GetBbox( m_lworld );
2331  delete lpoints;
2332  }
2333 
2335  bboxs.MapBbox( m_lworld );
2336  m_bbox.Expand( bboxs );
2337 
2338  if ( m_flags.m_editingCopy && m_spline )
2339  {
2340  m_spline = false;
2342  bboxs.MapBbox( m_lworld );
2343  m_bbox.Expand( bboxs );
2344  m_spline = true;
2345  }
2346 
2347  return true;
2348  }
2349  return false;
2350 }
2351 
2352 void a2dPolylineL::DoRender( a2dIterC& ic, OVERLAP clipparent )
2353 {
2354  if ( m_contourwidth )
2355  {
2356  //if ( a2dGlobals->GetRoundFactor() == 0 && m_pathtype == a2dPATH_END_ROUND )
2357  if ( m_pathtype == a2dPATH_END_ROUND )
2358  {
2359  a2dVertexList contourpoints = *m_lsegments;
2360  contourpoints.ConvertToLines();
2361 
2362  a2dLineSegment* segprev = NULL;
2363  a2dLineSegment* seg = NULL;
2364  a2dPoint2D first;
2365  a2dPoint2D second;
2366  a2dPoint2D offsetpoint;
2367 
2368  a2dVertexList::iterator iter = contourpoints.begin();
2369  while( iter != contourpoints.end() )
2370  {
2371  a2dVertexArray poly;
2372  a2dLineSegment* seg = *iter;
2373  seg = ( *iter );
2374 
2375  if ( segprev )
2376  {
2377  first = a2dPoint2D( segprev->m_x, segprev->m_y );
2378  second = a2dPoint2D( seg->m_x, seg->m_y );
2379 
2380  if ( first != second )
2381  {
2382  ic.GetDrawer2D()->DrawCircle( first.m_x, first.m_y, m_contourwidth / 2 );
2383  a2dLine line1( first, second );
2384  line1.CalculateLineParameters();
2385  offsetpoint = first;
2386  line1.Virtual_Point( offsetpoint, -m_contourwidth / 2 );
2387  poly.push_back( new a2dLineSegment( offsetpoint ) );
2388  offsetpoint = first;
2389  line1.Virtual_Point( offsetpoint, m_contourwidth / 2 );
2390  poly.push_back( new a2dLineSegment( offsetpoint ) );
2391  offsetpoint = second;
2392  line1.Virtual_Point( offsetpoint, m_contourwidth / 2 );
2393  poly.push_back( new a2dLineSegment( offsetpoint ) );
2394  offsetpoint = second;
2395  line1.Virtual_Point( offsetpoint, -m_contourwidth / 2 );
2396  poly.push_back( new a2dLineSegment( offsetpoint ) );
2397  ic.GetDrawer2D()->DrawPolygon( &poly );
2398  }
2399  }
2400  iter++;
2401  segprev = seg;
2402  }
2403  ic.GetDrawer2D()->DrawCircle( second.m_x, second.m_y, m_contourwidth / 2 );
2404  }
2405  else
2406  {
2407  a2dVertexList* contourpoints = m_lsegments->ConvertToContour( m_contourwidth / 2, m_pathtype );
2408  ic.GetDrawer2D()->DrawPolygon( contourpoints, m_spline );
2409  delete contourpoints;
2410  }
2411  }
2412  else
2413  ic.GetDrawer2D()->DrawLines( m_lsegments, m_spline );
2414 
2415  if ( m_crossAtVertex )
2416  {
2417  a2dStroke current = ic.GetDrawer2D()->GetDrawerStroke();
2418  a2dFill fillcurrent = ic.GetDrawer2D()->GetDrawerFill();
2419  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetHandle()->GetFill() );
2420  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetHandle()->GetStroke() );
2421 
2422  double x, y;
2425 
2426  a2dVertexList::iterator iter = m_lsegments->begin();
2427  a2dLineSegment* seg;
2428  while ( iter != m_lsegments->end() )
2429  {
2430  seg = ( *iter );
2431  x = seg->m_x;
2432  y = seg->m_y;
2433  double xd, yd;
2434  matrix.TransformPoint( x, y, xd, yd );
2435 
2436  ic.GetDrawer2D()->DrawCircle( xd, yd, a2dCrossAtVertexSize );
2437  iter++;
2438  }
2439  ic.GetDrawer2D()->PopTransform();
2440  ic.GetDrawer2D()->SetDrawerStroke( current );
2441  ic.GetDrawer2D()->SetDrawerFill( fillcurrent );
2442  }
2443 
2444  if ( m_flags.m_editingCopy )
2445  {
2447 
2448  if ( m_spline )
2449  {
2451  double x, y, w, h;
2452  x = untrans.GetMinX();
2453  y = untrans.GetMinY();
2454  w = untrans.GetWidth();
2455  h = untrans.GetHeight();
2456 
2457  ic.GetDrawer2D()->DrawLines( m_lsegments, false );
2458 
2459  a2dSmrtPtr<a2dRect> around = new a2dRect( x, y, w, h );
2460  around->SetIgnoreSetpending();
2461  around->SetRoot( m_root, false );
2462  around->Update( updatemask_force );
2463  around->SetStroke( *wxRED, 0, a2dSTROKE_DOT_DASH );
2464  around->SetFill( *a2dTRANSPARENT_FILL );
2465  around->Render( ic, _ON );
2466  }
2467 
2468  double x, y;
2469  double xp, yp;
2470  a2dVertexList::iterator iter = m_lsegments->begin();
2471  a2dLineSegment* seg;
2472  for ( int i = 0; i < m_lsegments->size()-1; i++ )
2473  {
2474  seg = ( *iter );
2475  if ( seg->GetBin() ) //selected?
2476  {
2477  x = seg->m_x;
2478  y = seg->m_y;
2479  a2dLineSegment* nextseg = *( m_lsegments->GetNextAround( iter ) );
2480  xp = nextseg->m_x;
2481  yp = nextseg->m_y;
2482 
2483  ic.GetDrawer2D()->SetDrawerFill( GetHabitat()->GetSelectFill() );
2484  ic.GetDrawer2D()->SetDrawerStroke( GetHabitat()->GetSelectStroke() );
2485  ic.GetDrawer2D()->DrawLine( x, y, xp, yp );
2486  }
2487  iter++;
2488  }
2489 
2491  }
2492 
2493  if ( m_begin )
2494  {
2495  a2dVertexList::iterator iter = m_lsegments->begin();
2496  a2dPoint2D point1 = GetPosXY();
2497  a2dPoint2D point2 = GetPosXY();
2498  if ( iter != m_lsegments->end() )
2499  {
2500  point1 = ( *iter )->GetPoint();
2501  iter++;
2502  if ( iter != m_lsegments->end() )
2503  point2 = ( *iter )->GetPoint();
2504  else
2505  point2 = point1;
2506  }
2507 
2508  double dx, dy;
2509  dx = point2.m_x - point1.m_x;
2510  dy = point2.m_y - point1.m_y;
2511  double ang1;
2512  if ( !dx && !dy )
2513  ang1 = 0;
2514  else
2515  ang1 = wxRadToDeg( atan2( dy, dx ) );
2516 
2517  a2dAffineMatrix lworld;
2518  //clockwise rotation so minus
2519  lworld.Scale( m_xscale, m_yscale, 0, 0 );
2520  lworld.Rotate( -ang1 );
2521  lworld.Translate( point1.m_x, point1.m_y );
2522 
2523  a2dIterCU cu( ic, lworld );
2524 
2525  m_begin->Render( ic, clipparent );
2526  }
2527 
2528  if ( m_end )
2529  {
2530  double dx = 0;
2531  double dy = 0;
2532  a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
2533  a2dPoint2D point1 = GetPosXY();
2534  a2dPoint2D point2 = GetPosXY();
2535  if ( iter != m_lsegments->rend() )
2536  {
2537  point1 = ( *iter )->GetPoint();
2538  while ( !dx && !dy && iter != m_lsegments->rend() )
2539  {
2540  point1 = ( *iter )->GetPoint();
2541  iter++;
2542  if ( iter != m_lsegments->rend() )
2543  point2 = ( *iter )->GetPoint();
2544  else
2545  point2 = point1;
2546  dx = point2.m_x - point1.m_x;
2547  dy = point2.m_y - point1.m_y;
2548  }
2549  }
2550 
2551  double ang2;
2552  if ( !dx && !dy )
2553  ang2 = 0;
2554  else
2555  ang2 = wxRadToDeg( atan2( dy, dx ) );
2556 
2557  a2dAffineMatrix tworld;
2558  //clockwise rotation so minus
2559  tworld.Scale( m_xscale, m_yscale, 0, 0 );
2560  tworld.Rotate( -ang2 );
2561  tworld.Translate( point1.m_x, point1.m_y );
2562 
2563  a2dIterCU cu( ic, tworld );
2564 
2565  m_end->Render( ic, clipparent );
2566  }
2567 }
2568 
2569 #if wxART2D_USE_CVGIO
2570 void a2dPolylineL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
2571 {
2572  a2dPolygonL::DoSave( parent, out, xmlparts, towrite );
2573  if ( xmlparts == a2dXmlSer_attrib )
2574  {
2575  if ( m_begin || m_end )
2576  {
2577  out.WriteAttribute( wxT( "xscale" ), m_xscale * out.GetScale() );
2578  out.WriteAttribute( wxT( "yscale" ), m_yscale * out.GetScale() );
2579  if ( m_begin )
2580  out.WriteAttribute( wxT( "begin" ), m_begin->GetUniqueSerializationId() );
2581  if ( m_end )
2582  out.WriteAttribute( wxT( "end" ), m_end->GetUniqueSerializationId() );
2583  }
2584  }
2585  else
2586  {
2587  if ( ( m_begin && !m_begin->GetCheck() ) ||
2588  ( m_end && !m_end->GetCheck() )
2589  )
2590  {
2591  //trick the system to have multiple refs on those objects, else we will not get an id attribute
2592  a2dCanvasObjectPtr begin = m_begin;
2593  a2dCanvasObjectPtr end = m_end;
2594 
2595  out.WriteStartElement( wxT( "derived" ) );
2596 
2597  if ( m_begin && !m_begin->GetCheck() )
2598  m_begin->Save( this, out, towrite );
2599  if ( m_end && !m_end->GetCheck() )
2600  m_end->Save( this, out, towrite );
2601 
2602  out.WriteEndElement();
2603  }
2604  }
2605 }
2606 
2607 void a2dPolylineL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
2608 {
2609  a2dPolygonL::DoLoad( parent, parser, xmlparts );
2610  if ( xmlparts == a2dXmlSer_attrib )
2611  {
2612  m_xscale = parser.GetAttributeValueDouble( wxT( "xscale" ) );
2613  m_yscale = parser.GetAttributeValueDouble( wxT( "yscale" ) );
2614 
2615  wxString resolveKey;
2616  if ( parser.HasAttribute( wxT( "begin" ) ) )
2617  {
2618  parser.ResolveOrAdd( ( a2dSmrtPtr<class a2dObject>* ) &m_begin, parser.GetAttributeValue( wxT( "begin" ) ) );
2619  }
2620  if ( parser.HasAttribute( wxT( "end" ) ) )
2621  {
2622  parser.ResolveOrAdd( ( a2dSmrtPtr<class a2dObject>* ) &m_end, parser.GetAttributeValue( wxT( "end" ) ) );
2623  }
2624  }
2625  else
2626  {
2627  if ( parser.GetTagName() != wxT( "derived" ) )
2628  return;
2629 
2630  parser.Require( START_TAG, wxT( "derived" ) );
2631  parser.Next();
2632 
2633  m_begin = (a2dCanvasObject*) parser.LoadOneObject( this );
2634  m_end = (a2dCanvasObject*) parser.LoadOneObject( this );
2635 
2636  parser.Require( END_TAG, wxT( "derived" ) );
2637  parser.Next();
2638  }
2639 }
2640 #endif //wxART2D_USE_CVGIO
2641 
2642 void a2dPolylineL::DoWalker( wxObject* parent, a2dWalkerIOHandler& handler )
2643 {
2644  handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectStart );
2645  a2dPolygonL::DoWalker( parent, handler );
2646  if ( m_begin )
2647  m_begin->Walker( this, handler );
2648 
2649  if ( m_end )
2650  m_end->Walker( this, handler );
2651 
2652  handler.WalkTask( parent, this, a2dWalker_a2dDerivedCanvasObjectEnd );
2653 }
2654 
2656 {
2657  a2dPoint2D P = a2dPoint2D( hitEvent.m_relx, hitEvent.m_rely );
2658  double pw = ic.GetWorldStrokeExtend();
2659  double margin = ic.GetTransformedHitMargin();
2660 
2661  hitEvent.m_how = PointOnPolyline( P, pw + margin + m_contourwidth / 2 );
2662 
2663  if( hitEvent.m_how.IsHit() )
2664  {
2665  //wxLogDebug(wxT(" hit at x=%12.6lf, y=%12.6lf"), P.m_x , P.m_y );
2666  return true;
2667  }
2668  bool ishit = false;
2669 
2670  if ( m_begin )
2671  {
2672  a2dVertexList::iterator iter = m_lsegments->begin();
2673  a2dPoint2D point1;
2674  a2dPoint2D point2;
2675  if ( iter != m_lsegments->end() )
2676  {
2677  point1 = ( *iter )->GetPoint();
2678  iter++;
2679  if ( iter != m_lsegments->end() )
2680  point2 = ( *iter )->GetPoint();
2681  else
2682  point2 = point1;
2683  }
2684 
2685  double dx, dy;
2686  dx = point2.m_x - point1.m_x;
2687  dy = point2.m_y - point1.m_y;
2688  double ang1;
2689  if ( !dx && !dy )
2690  ang1 = 0;
2691  else
2692  ang1 = wxRadToDeg( atan2( dy, dx ) );
2693 
2694  a2dAffineMatrix lworld;
2695  //clockwise rotation so minus
2696  lworld.Scale( m_xscale, m_yscale, 0, 0 );
2697  lworld.Rotate( -ang1 );
2698  lworld.Translate( point1.m_x, point1.m_y );
2699  a2dIterCU cu( ic, lworld );
2700  if( m_begin->IsHitWorld( ic, hitEvent ) != 0 )
2701  {
2702  // A hit on the begin object is treated like a hit on the begin vertex
2703  // To distinguish it, hit_member is set instead of hit_stroke
2704  hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_member;
2705  hitEvent.m_how.m_stroke1 = a2dHit::stroke1_outside;
2706  hitEvent.m_how.m_stroke2 = a2dHit::stroke2_vertex;
2707  hitEvent.m_how.m_index = 0;
2708  ishit = true;
2709  }
2710  }
2711 
2712  if ( m_end && ( !ishit || ( hitEvent.m_option & a2dCANOBJHITOPTION_ALL ) ) )
2713  {
2714  a2dVertexList::reverse_iterator iter = m_lsegments->rbegin();
2715  a2dPoint2D point1 = GetPosXY();
2716  a2dPoint2D point2 = GetPosXY();
2717  double dx = 0;
2718  double dy = 0;
2719  if ( iter != m_lsegments->rend() )
2720  {
2721  point1 = ( *iter )->GetPoint();
2722  while ( !dx && !dy && iter != m_lsegments->rend() )
2723  {
2724  point1 = ( *iter )->GetPoint();
2725  iter++;
2726  if ( iter != m_lsegments->rend() )
2727  point2 = ( *iter )->GetPoint();
2728  else
2729  point2 = point1;
2730  dx = point2.m_x - point1.m_x;
2731  dy = point2.m_y - point1.m_y;
2732  }
2733  }
2734  double ang2;
2735  if ( !dx && !dy )
2736  ang2 = 0;
2737  else
2738  ang2 = wxRadToDeg( atan2( dy, dx ) );
2739 
2740  a2dAffineMatrix tworld;
2741  //clockwise rotation so minus
2742  tworld.Scale( m_xscale, m_yscale, 0, 0 );
2743  tworld.Rotate( -ang2 );
2744  tworld.Translate( point1.m_x, point1.m_y );
2745  a2dIterCU cu( ic, tworld );
2746  if ( m_end->IsHitWorld( ic, hitEvent ) != 0 )
2747  {
2748  // A hit on the end object is treated like a hit on the end vertex
2749  hitEvent.m_how.m_hit = hitEvent.m_how.m_hit | a2dHit::hit_member;
2750  hitEvent.m_how.m_stroke1 = a2dHit::stroke1_outside;
2751  hitEvent.m_how.m_stroke2 = a2dHit::stroke2_vertex;
2752  hitEvent.m_how.m_index = m_lsegments->size() - 1;
2753  ishit = true;
2754  }
2755  }
2756 
2757  return hitEvent.m_how.IsHit();
2758 }
2759 
2760 a2dHit a2dPolylineL::PointOnPolyline( const a2dPoint2D& P, double margin )
2761 {
2762  a2dVertexList* rlist;
2763  if ( m_spline )
2764  {
2765 
2766  a2dVertexList* lpoints = new a2dVertexList();
2767  a2dVertexList::iterator iter = m_lsegments->begin();
2768  while ( iter != m_lsegments->end() )
2769  {
2770  a2dLineSegment* point = ( *iter )->Clone();
2771  lpoints->push_back( point );
2772  iter++;
2773  }
2774 
2775  lpoints->ConvertIntoSplinedPolyline( 10 );
2776  rlist = lpoints;
2777  }
2778  else
2779  rlist = m_lsegments;
2780 
2781  a2dHit result = rlist->HitTestPolyline( P, margin );
2782 
2783  if ( m_spline )
2784  delete rlist;
2785 
2786  return result;
2787 }
2788 
2789 bool a2dPolylineL::DoCanConnectWith( a2dIterC& ic, a2dPin* pin, double WXUNUSED( margin ), bool autocreate )
2790 {
2791  RemovePins( true, true );
2792 
2793  //if pin is of this wire itself, we do not want it to connect.
2794  if( pin->GetParent() == this )
2795  return false;
2796 
2797  //the original has this property set
2798  if ( a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( this ) )
2799  return false;
2800 
2801  if ( autocreate )
2802  {
2803  // Create dynamic pins
2804  // First test if it is a hit, it is useless to create pins not on the wire.
2805  a2dHitEvent hitevent = a2dHitEvent( pin->GetAbsX(), pin->GetAbsY(), false );
2806  if( IsHitWorld( ic, hitevent ) )
2807  {
2808  bool found = false;
2809  // generate pins which can connect this pin
2810  found = GeneratePins( pin->GetPinClass(), a2d_GeneratePinsForPinClass, pin->GetPosX(), pin->GetPosY() ) || found;
2811  return found;
2812  }
2813  }
2814  return false;
2815 }
2816 
2817 bool a2dPolylineL::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double x, double y, double margin )
2818 {
2819  a2dPinClass* toCreate;
2820  if ( GetGeneratePins() && ( toCreate = toConnectTo->GetPinClassForTask( task, this ) ) )
2821  {
2822  m_flags.m_visiblechilds = true;
2823  bool end = false;
2824  bool begin = false;
2825  if ( !HasPinNamed( wxT( "begin" ) ) )
2826  {
2827  a2dVertexList::iterator iter = m_lsegments->begin();
2828  assert( m_lsegments->size() );
2829  AddPin( wxT( "begin" ), ( *iter )->m_x, ( *iter )->m_y, a2dPin::temporaryObjectPin, toCreate );
2830  }
2831  else
2832  begin = true;
2833 
2834  if ( !HasPinNamed( wxT( "end" ) ) )
2835  {
2836  a2dVertexList::iterator iter = m_lsegments->end();
2837  assert( m_lsegments->size() );
2838  iter--;
2839  AddPin( wxT( "end" ), ( *iter )->m_x, ( *iter )->m_y, a2dPin::temporaryObjectPin, toCreate );
2840  }
2841  else
2842  end = true;
2843 
2844  if ( /*begin && end &&*/ m_lsegments->size() > 0 )
2845  {
2846  // Find the rastered point on the line closest to the polygon line
2847  double xNear, yNear;
2848  if( FindNearPoint( &m_lworld, x, y, &xNear, &yNear ) )
2849  {
2850  a2dAffineMatrix inverse = m_lworld;
2851  inverse.Invert();
2852  double xNearLocal, yNearLocal;
2853  inverse.TransformPoint( xNear, yNear, xNearLocal, yNearLocal );
2854 
2855  //now we create a dynamic pin of the same class as a connected pin.
2856  a2dPin* pin = AddPin( wxT( "dynamic" ), xNearLocal, yNearLocal, a2dPin::temporaryObjectPin | a2dPin::dynamic, toCreate );
2858  pin->SetMouseInObject( true );
2859  }
2860  }
2861 
2862  wxASSERT( HasPins() );
2864 
2865  return true;
2866  }
2867  return false;
2868 }
2869 
2870 bool a2dPolylineL::FindNearPoint( const a2dAffineMatrix* cworld, double xIn, double yIn, double* xOut, double* yOut )
2871 {
2872  if( GetNumberOfSegments() < 2 )
2873  return false;
2874 
2875  a2dAffineMatrix tworld;
2876  if( cworld )
2877  {
2878  tworld = *cworld;
2879  tworld *= m_lworld;
2880  }
2881  a2dAffineMatrix inverse = tworld;
2882  inverse.Invert();
2883 
2884  double xh, yh;
2885  inverse.TransformPoint( xIn, yIn, xh, yh );
2886 
2887  double dist;
2888  double minDist = DBL_MAX;
2889 
2890  a2dPoint2D p = a2dPoint2D( xh, yh );
2891  a2dPoint2D p1, p2, pBest;
2892 
2893  // If the polyline is splined, first convert the vertex list to a linearized spline
2894  a2dVertexList* rlist;
2895  if( m_spline )
2896  rlist = m_lsegments->ConvertSplinedPolyline( 10 );
2897  else
2898  rlist = m_lsegments;
2899 
2900  // Find the closest point on the line
2901  a2dVertexList::iterator iter = rlist->begin();
2902  p2 = ( *iter )->GetPoint();
2903  while( iter != rlist->end() )
2904  {
2905  p1 = p2;
2906  iter++;
2907  if ( iter == rlist->end() ) break;
2908  p2 = ( *iter )->GetPoint();
2909 
2910  a2dLine line( p1, p2 );
2911  a2dPoint2D pBestLine;
2912  dist = line.PointDistance( p, &pBestLine );
2913  if( dist < minDist )
2914  {
2915  minDist = dist;
2916  pBest = pBestLine;
2917  }
2918  }
2919 
2920  // Clean up the linearized vertex list
2921  if ( m_spline )
2922  delete rlist;
2923 
2924  // Transform the point back
2925  tworld.TransformPoint( pBest.m_x, pBest.m_y, *xOut, *yOut );
2926 
2927  return true;
2928 }
2929 
2930 bool a2dPolylineL::FindNearPointOrtho( const a2dAffineMatrix* cworld, double xIn, double yIn, double* xOut, double* yOut )
2931 {
2932  if( GetNumberOfSegments() < 2 )
2933  return false;
2934 
2935  bool result = false;
2936 
2937  a2dAffineMatrix tworld;
2938  if( cworld )
2939  {
2940  tworld = *cworld;
2941  tworld *= m_lworld;
2942  }
2943  a2dAffineMatrix inverse = tworld;
2944  inverse.Invert();
2945 
2946  double xh, yh;
2947  inverse.TransformPoint( xIn, yIn, xh, yh );
2948 
2949  double dist;
2950  double minDist = DBL_MAX;
2951 
2952  a2dPoint2D p = a2dPoint2D( xh, yh );
2953  a2dPoint2D p1, p2, pBest;
2954 
2955  // If the polyline is splined, first convert the vertex list to a linearized spline
2956  a2dVertexList* rlist;
2957  if( m_spline )
2958  rlist = m_lsegments->ConvertSplinedPolyline( 10 );
2959  else
2960  rlist = m_lsegments;
2961 
2962  // Find the closest point on the line
2963  a2dVertexList::iterator iter = rlist->begin();
2964  p2 = ( *iter )->GetPoint();
2965  while( iter != rlist->end() )
2966  {
2967  p1 = p2;
2968  iter++;
2969  if ( iter == rlist->end() ) break;
2970  p2 = ( *iter )->GetPoint();
2971 
2972  a2dLine line( p1, p2 );
2973  a2dPoint2D pBestLine;
2974  dist = line.PointDistanceOrhto( p, &pBestLine );
2975  if( dist < minDist )
2976  {
2977  minDist = dist;
2978  pBest = pBestLine;
2979  result = true;
2980  }
2981  }
2982 
2983  // Clean up the linearized vertex list
2984  if ( m_spline )
2985  delete rlist;
2986 
2987  // Transform the point back
2988  tworld.TransformPoint( pBest.m_x, pBest.m_y, *xOut, *yOut );
2989 
2990  return result;
2991 }
2992 
2993 bool a2dPolylineL::MoveDynamicPinCloseTo( a2dPin* pin, const a2dPoint2D& point, bool final )
2994 {
2995  wxASSERT( pin );
2996  wxASSERT( pin->IsDynamicPin() );
2997  wxASSERT( pin->GetParent() == this );
2998 
2999  a2dPoint2D pointLocal;
3000  a2dAffineMatrix trns = pin->GetParent()->GetTransformMatrix();
3001  trns.Invert();
3002  trns.TransformPoint( point, &pointLocal );
3003 
3004  double xNew, yNew, xNewO, yNewO;
3005  bool orthook = FindNearPointOrtho( 0, pointLocal.m_x, pointLocal.m_y, &xNewO, &yNewO );
3006  bool straightok = FindNearPoint( 0, pointLocal.m_x, pointLocal.m_y, &xNew, &yNew );
3007 
3008  if(
3009  orthook && PointDistSqr( pointLocal.m_x, pointLocal.m_y, xNewO, yNewO ) < PointDistSqr( pointLocal.m_x, pointLocal.m_y, xNew, yNew ) * 4 ||
3010  orthook && !straightok
3011  )
3012  {
3013  xNew = xNewO;
3014  yNew = yNewO;
3015  }
3016 
3017  a2dPoint2D pos = pin->GetPosXY();
3018 
3019  if( ( xNew != pos.m_x || yNew != pos.m_y ) && ( orthook || straightok ) )
3020  {
3021  if ( final )
3022  m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
3023  else
3024  pin->SetPosXY( xNew, yNew );
3025  return true;
3026  }
3027  return false;
3028 }
3029 
3031 {
3032  return HasPinNamed( wxT( "begin" ) );
3033 }
3034 
3036 {
3037  return HasPinNamed( wxT( "end" ) );
3038 }
3039 
3041 {
3042  switch( *i )
3043  {
3044  case 0:
3045  {
3046  a2dPin* pin = FindBeginPin();
3047  ( *i )++;
3048  if( pin ) return pin;
3049  }
3050  // fall through if no pin found
3051  case 1:
3052  {
3053  a2dPin* pin = FindEndPin();
3054  ( *i )++;
3055  if( pin ) return pin;
3056  }
3057  // fall through if no pin found
3058  default:
3059  return 0;
3060  }
3061 }
3062 
3063 int a2dPolylineL::FindSegmentIndex( const a2dPoint2D& point, double margin )
3064 {
3065  a2dHit hit = m_lsegments->HitTestPolyline( point, margin );
3066 
3067  if ( hit.IsHit() )
3068  {
3069  return hit.m_index;
3070  }
3071  return -1;
3072 }
3073 
3074 int a2dPolylineL::FindPinSegmentIndex( a2dPin* pinToFind, double margin )
3075 {
3076  a2dHit hit = m_lsegments->HitTestPolyline( pinToFind->GetPosXY(), margin );
3077 
3078  if ( hit.IsHit() )
3079  {
3080  return hit.m_index;
3081  }
3082  return -1;
3083 }
3084 
3086 {
3087  a2dHit hit = m_lsegments->HitTestPolyline( pinToFind->GetPosXY(), margin );
3088 
3089  if ( hit.IsHit() )
3090  {
3091  a2dVertexList::iterator iter = GetSegmentAtIndex( hit.m_index );
3092  return *iter;
3093  }
3094  return NULL;
3095 }
3096 
3097 a2dLineSegment* a2dPolylineL::GetFirstPoint() const
3098 {
3099  a2dVertexList::const_iterator iter = m_lsegments->begin();
3100  if ( iter != m_lsegments->end() )
3101  return iter->Get();
3102  return NULL;
3103 }
3104 
3105 a2dLineSegment* a2dPolylineL::GetLastPoint() const
3106 {
3107  if ( m_lsegments->size() )
3108  {
3109  a2dVertexList::const_iterator iter = m_lsegments->end();
3110  iter--;
3111  return iter->Get();
3112  }
3113  return NULL;
3114 }
3115 
3116 void a2dPolylineL::OnChar( wxKeyEvent& event )
3117 {
3118  if ( m_flags.m_editingCopy )
3119  {
3120  switch( event.GetKeyCode() )
3121  {
3122  case WXK_DELETE:
3123  {
3124  if ( m_lsegments->size() <= 2 )
3125  {
3126  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
3127  break; // leaf at least one segment
3128  }
3129 
3130  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
3131  //first delete selected segments ( nodes maybe selcted, and those nodes maybe removed because of this. (notice --m_childobjects->end())
3132  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != --m_childobjects->end(); ++iter )
3133  {
3134  if ( m_lsegments->size() <= 2 )
3135  {
3136  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
3137  break; // leaf at least one segment
3138  }
3139  a2dCanvasObject* obj = *iter;
3140 
3141  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
3142 
3143  if ( handle && !handle->GetRelease( ) )
3144  {
3145  a2dVertexList::iterator iterpoly = handle->GetNode();
3146  a2dLineSegment* segment = *( iterpoly );
3147  if ( segment->GetBin() ) //selected?
3148  {
3149  iter++;
3150  a2dPolyHandleL* handle2 = wxDynamicCast( (*iter).Get(), a2dPolyHandleL );
3151  iter--;
3152  a2dLineSegment* segmentOrgNext = *( handle2->GetNodeOrg() );
3153  a2dLineSegment* segmentOrg = *( handle->GetNodeOrg() );
3154 
3155  double xn,yn;
3156  xn = (handle->GetPosX() + handle2->GetPosX())/2.0;
3157  yn = (handle->GetPosY() + handle2->GetPosY())/2.0;
3158  handle2->SetPosXY( xn, yn );
3159  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
3160  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, xn, yn, segmentOrgNext, false ) );
3161  iterpoly = m_lsegments->erase( iterpoly );
3162  (*iterpoly)->m_x = xn; (*iterpoly)->m_y = yn;
3163  ReleaseChild( handle );
3164  }
3165  }
3166  }
3167 
3168  //now delete selected handles (only those which were not released above).
3169  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
3170  {
3171  a2dCanvasObject* obj = *iter;
3172 
3173  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
3174 
3175  if ( handle && !handle->GetRelease( ) && handle->GetSelected() )
3176  {
3177  a2dVertexList::iterator iterpoly = handle->GetNode();
3178  a2dLineSegment* segment = *( iterpoly );
3179  a2dVertexList::iterator iterorg = handle->GetNodeOrg();
3180  a2dLineSegment* segmentOrg = *( iterorg );
3181 
3182  if ( m_lsegments->size() <= 2 )
3183  {
3184  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
3185  break; // leaf at least one segment
3186  }
3187  else
3188  {
3189  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
3190  m_lsegments->erase( iterpoly );
3191  ReleaseChild( handle );
3192  }
3193  }
3194  }
3195  original->AdjustAfterChange( true );
3196  }
3197  break;
3198  default:
3199  event.Skip();
3200  }
3201  }
3202  else
3203  event.Skip();
3204 }
3205 
3206 //----------------------------------------------------------------------------
3207 // a2dPolygonLClipper
3208 //----------------------------------------------------------------------------
3209 
3211  : a2dPolygonL()
3212 {
3213  if ( &bbox != &wxNonValidBbox )
3214  {
3215  AddPoint( bbox.GetMinX(), bbox.GetMinY() );
3216  AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
3217  AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
3218  AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
3219  }
3220 
3221  m_spline = false;
3222 }
3223 
3225  : a2dPolygonL( points, spline )
3226 {
3227 }
3228 
3230 {
3231 }
3232 
3234 {
3235  Clear();
3236  if ( &bbox != &wxNonValidBbox )
3237  {
3238  AddPoint( bbox.GetMinX(), bbox.GetMinY() );
3239  AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
3240  AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
3241  AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
3242  }
3243 }
3244 
3246 {
3247  return new a2dPolygonLClipper( *this, options, refs );
3248 };
3249 
3251  : a2dPolygonL( other, options, refs )
3252 {
3253 }
3254 
3256 {
3257  if ( m_lsegments->size() )
3258  {
3259  a2dIterCU cu( ic, m_ClipLworld );
3260 
3261  //if ( m_flags.m_editingCopy )
3262  ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE );
3263  ic.GetDrawer2D()->ExtendAndPushClippingRegion( m_lsegments, m_spline, wxWINDING_RULE, a2dCLIP_AND );
3264  }
3265 
3266  a2dCanvasObject::Render( ic, clipparent );
3267 
3268  if ( m_lsegments->size() )
3270 }
3271 
3273 {
3274  a2dCanvasObject::Update( mode );
3275 
3278 
3279  if ( m_flags.m_editingCopy && m_spline )
3280  {
3281  m_spline = false;
3283  bboxs.MapBbox( m_ClipLworld );
3284  m_bbox.Expand( bboxs );
3285  m_spline = true;
3286  }
3287 
3288  return false;
3289 }
3290 
3291 void a2dPolygonLClipper::DoRender( a2dIterC& WXUNUSED( ic ), OVERLAP WXUNUSED( clipparent ) )
3292 {
3293  if ( m_flags.m_editingCopy )
3294  {
3295  //ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE);
3296  }
3297 }
3298 
3300 {
3301  m_ClipLworld = mat; SetPending( true );
3302 }
3303 
3304 //----------------------------------------------------------------------------
3305 // a2dPolygonLClipper2
3306 //----------------------------------------------------------------------------
3307 
3308 a2dPolygonLClipper2::a2dPolygonLClipper2( a2dBoundingBox& bbox )
3309  : a2dPolygonL()
3310 {
3311  if ( &bbox != &wxNonValidBbox )
3312  {
3313  AddPoint( bbox.GetMinX(), bbox.GetMinY() );
3314  AddPoint( bbox.GetMinX(), bbox.GetMaxY() );
3315  AddPoint( bbox.GetMaxX(), bbox.GetMaxY() );
3316  AddPoint( bbox.GetMaxX(), bbox.GetMinY() );
3317  }
3318 
3319  m_spline = false;
3320 }
3321 
3322 a2dPolygonLClipper2::a2dPolygonLClipper2( a2dVertexList* points, bool spline )
3323  : a2dPolygonL( points, spline )
3324 {
3325 }
3326 
3327 a2dPolygonLClipper2::~a2dPolygonLClipper2()
3328 {
3329 }
3330 
3332 {
3333  return new a2dPolygonLClipper2( *this, options, refs );
3334 };
3335 
3336 a2dPolygonLClipper2::a2dPolygonLClipper2( const a2dPolygonLClipper2& other, CloneOptions options, a2dRefMap* refs )
3337  : a2dPolygonL( other, options, refs )
3338 {
3339 }
3340 
3342 {
3343  if ( m_lsegments->size() )
3344  {
3345  a2dIterCU cu( ic, this );
3346 
3347  if ( !m_flags.m_editingCopy )
3348  ic.GetDrawer2D()->ExtendAndPushClippingRegion( m_lsegments, m_spline, wxWINDING_RULE, a2dCLIP_AND );
3349  }
3350 
3351  a2dCanvasObject::Render( ic, clipparent );
3352 
3353  if ( m_lsegments->size() )
3354  if ( !m_flags.m_editingCopy )
3356 }
3357 
3359 {
3360  a2dCanvasObject::Update( mode );
3361 
3363  m_bbox.MapBbox( m_lworld );
3364 
3365  if ( m_flags.m_editingCopy && m_spline )
3366  {
3367  m_spline = false;
3369  bboxs.MapBbox( m_lworld );
3370  m_bbox.Expand( bboxs );
3371  m_spline = true;
3372  }
3373 
3374  return false;
3375 }
3376 
3377 void a2dPolygonLClipper2::DoRender( a2dIterC& ic, OVERLAP WXUNUSED( clipparent ) )
3378 {
3379  //if ( m_flags.m_editingCopy )
3380  {
3381  ic.GetDrawer2D()->DrawPolygon( m_lsegments, m_spline, wxWINDING_RULE );
3382  }
3383 }
3384 
3385 //----------------------------------------------------------------------------
3386 // a2dPolyHandleL
3387 //----------------------------------------------------------------------------
3388 
3389 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIH = NULL;
3390 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIH = NULL;
3391 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIV1 = NULL;
3392 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIV1 = NULL;
3393 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpXIV2 = NULL;
3394 a2dPropertyIdDouble* a2dPolyHandleL::PROPID_tmpYIV2 = NULL;
3395 
3396 INITIALIZE_PROPERTIES( a2dPolyHandleL, a2dHandle )
3397 {
3404  return true;
3405 }
3406 
3408  : a2dHandle( NULL, 0, 0, wxT( "dummy" ), GetHabitat()->GetHandle()->GetWidth(), GetHabitat()->GetHandle()->GetHeight() )
3409 {
3410  m_arcHandle = false;
3411  m_dragging = true;
3412  m_lsegments = NULL;
3413  m_lsegmentsOrg = NULL;
3414 }
3415 
3416 a2dPolyHandleL::a2dPolyHandleL( a2dPolygonL* parent, a2dVertexList::iterator segNode, a2dVertexList::iterator segNodeOrg,
3417  a2dSmrtPtr<a2dVertexList> lsegments,
3418  a2dSmrtPtr<a2dVertexList> lsegmentsOrg,
3419  const wxString& name )
3420  : a2dHandle( parent, ( *segNode )->m_x, ( *segNode )->m_y, name )
3421 {
3422  m_segNode = segNode;
3423  m_segNodeOrg = segNodeOrg;
3424  m_lsegments = lsegments;
3425  m_lsegmentsOrg = lsegmentsOrg;
3426  m_arcHandle = false;
3427  m_dragging = false;
3428 }
3429 
3430 a2dPolyHandleL::a2dPolyHandleL( a2dPolygonL* parent, a2dVertexList::iterator segNode, a2dVertexList::iterator segNodeOrg,
3431  a2dSmrtPtr<a2dVertexList> lsegments,
3432  a2dSmrtPtr<a2dVertexList> lsegmentsOrg,
3433  double xc, double yc, const wxString& name )
3434  : a2dHandle( parent, xc, yc, name )
3435 {
3436  m_segNode = segNode;
3437  m_segNodeOrg = segNodeOrg;
3438  m_lsegments = lsegments;
3439  m_lsegmentsOrg = lsegmentsOrg;
3440  m_arcHandle = false;
3441  m_dragging = false;
3442 }
3443 
3445  : a2dHandle( other, options, refs )
3446 {
3447  m_segNode = other.m_segNode;
3448  m_segNodeOrg = other.m_segNodeOrg;
3449  m_arcHandle = other.m_arcHandle;
3450  m_lsegments = other.m_lsegments;
3451  m_lsegmentsOrg = other.m_lsegmentsOrg;
3452  m_dragging = false;
3453 }
3454 
3456 {
3457 }
3458 
3460 {
3461  return new a2dPolyHandleL( *this, options, refs );
3462 };
3463 
3464 //----------------------------------------------------------------------------
3465 // a2dSurface
3466 //----------------------------------------------------------------------------
3467 IMPLEMENT_DYNAMIC_CLASS( a2dSurface, a2dPolygonL )
3468 
3469 BEGIN_EVENT_TABLE( a2dSurface, a2dPolygonL )
3470  EVT_CANVASOBJECT_MOUSE_EVENT( a2dSurface::OnCanvasObjectMouseEvent )
3471  EVT_CANVASHANDLE_MOUSE_EVENT( a2dSurface::OnHandleEvent )
3472  EVT_CHAR( a2dSurface::OnChar )
3473 END_EVENT_TABLE()
3474 
3475 a2dSurface::a2dSurface()
3476  : a2dPolygonL()
3477 {
3478  m_lsegments = new a2dVertexList();
3479 }
3480 
3481 a2dSurface::a2dSurface( a2dVertexListPtr points, bool spline )
3482  : a2dPolygonL( points, spline )
3483 {
3484 }
3485 
3486 a2dSurface::~a2dSurface()
3487 {
3488 }
3489 
3491 {
3492  m_lsegments->clear();
3493  m_holes.clear();
3494 }
3495 
3496 a2dSurface::a2dSurface( const a2dSurface& other, CloneOptions options, a2dRefMap* refs )
3497  : a2dPolygonL( other, options, refs )
3498 {
3499  for( a2dListOfa2dVertexList::const_iterator iterp = other.m_holes.begin(); iterp != other.m_holes.end(); iterp++ )
3500  {
3501  a2dVertexListPtr vlist = ( *iterp );
3502  a2dVertexListPtr holepoints = new a2dVertexList();
3503  *holepoints = *vlist;
3504  m_holes.push_back( holepoints );
3505 
3506  }
3507 }
3508 
3510 {
3511  return new a2dSurface( *this, options, refs );
3512 };
3513 
3514 a2dVertexList* a2dSurface::GetAsVertexList( bool& returnIsPolygon ) const
3515 {
3516  return NULL;
3517 }
3518 
3520 {
3521  a2dCanvasObjectList* polygons = new a2dCanvasObjectList();
3522 
3523  a2dVertexList* conSegm = new a2dVertexList( *(m_lsegments.Get()) );
3524  a2dPolygonL* contour = new a2dPolygonL( new a2dVertexList( *(m_lsegments.Get()) ) );
3525  contour->SetStroke( this->GetStroke() );
3526  contour->SetFill( this->GetFill() );
3527  contour->SetLayer( m_layer );
3528  contour->SetContourWidth( GetContourWidth() );
3529  contour->SetRoot( m_root, false );
3530  if ( transform )
3531  contour->EliminateMatrix();
3532  polygons->push_back( contour );
3533 
3534  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3535  {
3536  a2dVertexListPtr vlist = ( *iterp );
3537  a2dPolygonL* hole = new a2dPolygonL( new a2dVertexList( *(vlist.Get()) ) );
3538  hole->SetStroke( this->GetStroke() );
3539  hole->SetFill( this->GetFill() );
3540  hole->SetLayer( m_layer );
3541  hole->SetContourWidth( GetContourWidth() );
3542  hole->SetRoot( m_root, false );
3543  if ( hole )
3544  hole->EliminateMatrix();
3545  polygons->push_back( hole );
3546  }
3547  return polygons;
3548 }
3549 
3551 {
3552  a2dCanvasObjectList* polygons = new a2dCanvasObjectList();
3553 
3554  a2dVertexList* conSegm = new a2dVertexList( *(m_lsegments.Get()) );
3555  conSegm->push_back( conSegm->front()->Clone() );
3556  a2dPolylineL* contour = new a2dPolylineL( conSegm );
3557  contour->SetStroke( this->GetStroke() );
3558  contour->SetFill( this->GetFill() );
3559  contour->SetLayer( m_layer );
3560  contour->SetContourWidth( GetContourWidth() );
3561  contour->SetRoot( m_root, false );
3562  if ( transform )
3563  contour->EliminateMatrix();
3564  polygons->push_back( contour );
3565 
3566  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3567  {
3568  a2dVertexListPtr vlist = ( *iterp );
3569  a2dVertexListPtr vlistcopy = new a2dVertexList( *(vlist.Get()) );
3570  vlistcopy->push_back( vlistcopy->front()->Clone() );
3571  a2dPolylineL* hole = new a2dPolylineL( vlistcopy );
3572  hole->SetStroke( this->GetStroke() );
3573  hole->SetFill( this->GetFill() );
3574  hole->SetLayer( m_layer );
3575  hole->SetContourWidth( GetContourWidth() );
3576  hole->SetRoot( m_root, false );
3577  if ( hole )
3578  hole->EliminateMatrix();
3579  polygons->push_back( hole );
3580  }
3581  return polygons;
3582 }
3583 
3585 {
3586  a2dVpath* segments = m_lsegments->ConvertToVpath( true, true );
3587 
3588  a2dVpathSegment* lastseg = segments->back();
3589  lastseg->SetClose( a2dPATHSEG_END_OPEN );
3590 
3591  a2dVpathSegment* segvec = NULL;
3592  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3593  {
3594  a2dVertexListPtr vlist = ( *iterp );
3595  if ( vlist->size() > 1 )
3596  {
3597  a2dVertexList::iterator iter = vlist->begin();
3598  a2dLineSegmentPtr seg = *iter;
3599  segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO_NOSTROKE );
3600  segments->push_back( segvec );
3601 
3602  while ( iter != vlist->end() )
3603  {
3604  a2dLineSegmentPtr seg = *iter;
3605  segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO );
3606  segments->push_back( segvec );
3607  iter++;
3608  }
3609  seg = *( vlist->begin() );
3610  segvec = new a2dVpathSegment( seg->m_x, seg->m_y, a2dPATHSEG_LINETO );
3611  segments->push_back( segvec );
3612  segvec = new a2dVpathSegment( lastseg->m_x1, lastseg->m_y1, a2dPATHSEG_LINETO_NOSTROKE );
3613  segments->push_back( segvec );
3614  }
3615  }
3616  if ( segvec )
3617  segvec->SetClose( a2dPATHSEG_END_CLOSED );
3618 
3619  a2dVectorPath* canpath = new a2dVectorPath( segments );
3620  if ( transform )
3621  segments->Transform( m_lworld );
3622  canpath->SetStroke( this->GetStroke() );
3623  canpath->SetFill( this->GetFill() );
3624  canpath->SetLayer( m_layer );
3625  canpath->SetContourWidth( GetContourWidth() );
3626  a2dCanvasObjectList* canpathlist = new a2dCanvasObjectList();
3627  canpathlist->push_back( canpath );
3628 
3629  return canpathlist;
3630 }
3631 
3632 a2dCanvasObjectList* a2dSurface::GetAsLinesArcs( bool transform )
3633 {
3634  a2dCanvasObjectList* linesAnArcs = new a2dCanvasObjectList();
3635 
3636  double xp = m_lsegments->back()->m_x;
3637  double yp = m_lsegments->back()->m_y;
3638  if ( transform )
3639  m_lworld.TransformPoint( xp, yp, xp, yp );
3640  a2dCanvasObject* obj;
3641  for( a2dVertexList::iterator iter = m_lsegments->begin(); iter != m_lsegments->end(); ++iter )
3642  {
3643  double x, y, xm, ym;
3644  a2dLineSegment* seg = *iter;
3645  x = seg->m_x; y = seg->m_y;
3646  if ( transform )
3647  m_lworld.TransformPoint( x, y, x, y );
3648  if ( seg->GetArc() )
3649  {
3650  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
3651  xm = cseg->m_x2; ym = cseg->m_y2;
3652  if ( transform )
3653  m_lworld.TransformPoint( xm, ym, xm, ym );
3654  a2dArc* arc = new a2dArc();
3655  arc->SetChord( true );
3656  obj = arc;
3657  arc->Set( xp, yp, xm, ym, x, y );
3658  linesAnArcs->push_back( arc );
3659  }
3660  else
3661  {
3662  a2dSLine* line = new a2dSLine( xp, yp, x, y );
3663  obj = line;
3664  linesAnArcs->push_back( line );
3665  }
3666 
3667  obj->SetStroke( this->GetStroke() );
3668  obj->SetFill( this->GetFill() );
3669  obj->SetLayer( m_layer );
3670  obj->SetContourWidth( GetContourWidth() );
3671  obj->SetRoot( m_root, false );
3672 
3673  xp = x;
3674  yp = y;
3675  }
3676 
3677  return linesAnArcs;
3678 }
3679 
3680 void a2dSurface::AddHole( a2dVertexListPtr holepoints )
3681 {
3682  m_holes.push_back( holepoints );
3683 }
3684 
3686 {
3687  a2dPolygonL::RemoveRedundantPoints( sendCommandsTo );
3688 }
3689 
3691 {
3694 }
3695 
3696 a2dBoundingBox a2dSurface::DoGetUnTransformedBbox( a2dBboxFlags WXUNUSED( flags ) ) const
3697 {
3698  a2dBoundingBox bbox;
3699  if ( m_spline )
3700  {
3701  a2dVertexList* lpoints = new a2dVertexList();
3702 
3703  *lpoints = *m_lsegments;
3704  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
3705  bbox = lpoints->GetBbox();
3706  delete lpoints;
3707  }
3708  else
3709  bbox = m_lsegments->GetBbox();
3710 
3711  if ( m_contourwidth > 0 )
3712  bbox.Enlarge( m_contourwidth / 2 );
3713 
3714  return bbox;
3715 }
3716 
3717 bool a2dSurface::DoUpdate( UpdateMode mode, const a2dBoundingBox& childbox, const a2dBoundingBox& clipbox, const a2dBoundingBox& propbox )
3718 {
3719  if ( !m_bbox.GetValid() )
3720  {
3721  if ( m_spline )
3722  {
3723  a2dVertexList* lpoints = new a2dVertexList();
3724 
3725  *lpoints = *m_lsegments;
3726  lpoints->ConvertIntoSplinedPolygon( double(GetHabitat()->GetAberPolyToArc()) / m_root->GetUnitsScale() );
3727  m_bbox = lpoints->GetBbox( m_lworld );
3728  delete lpoints;
3729  }
3730 
3732  bboxs.MapBbox( m_lworld );
3733  m_bbox.Expand( bboxs );
3734 
3735  if ( m_flags.m_editingCopy && m_spline )
3736  {
3737  m_spline = false;
3739  bboxs.MapBbox( m_lworld );
3740  m_bbox.Expand( bboxs );
3741  m_spline = true;
3742  }
3743  return true;
3744  }
3745  return false;
3746 }
3747 
3748 void a2dSurface::DoRender( a2dIterC& ic, OVERLAP clipparent )
3749 {
3750  // x windows requires last point to be eqaul to first for polypolygons.
3751  a2dListOfa2dVertexList drawable;
3752  a2dLineSegmentPtr last = m_lsegments->front();
3753  m_lsegments->push_back( last );
3754  drawable.push_back( m_lsegments );
3755  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3756  {
3757  a2dVertexListPtr vlist = ( *iterp );
3758  if ( vlist->size() > 1 )
3759  {
3760  a2dLineSegmentPtr last = vlist->front();
3761  vlist->push_back( last );
3762  drawable.push_back( vlist );
3763  }
3764  }
3765  ic.GetDrawer2D()->DrawPolyPolygon( drawable, wxWINDING_RULE );
3766  m_lsegments->pop_back();
3767  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3768  {
3769  a2dVertexListPtr vlist = ( *iterp );
3770  if ( vlist->size() > 1 )
3771  {
3772  vlist->pop_back();
3773  }
3774  }
3775 }
3776 
3777 #if wxART2D_USE_CVGIO
3778 void a2dSurface::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
3779 {
3780  a2dPolygonL::DoSave( parent, out, xmlparts, towrite );
3781  if ( xmlparts == a2dXmlSer_attrib )
3782  {
3783  out.WriteAttribute( wxT( "holes" ), m_holes.size() );
3784  }
3785  else
3786  {
3787  unsigned int i = 0;
3788  for( a2dListOfa2dVertexList::iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3789  {
3790  out.WriteStartElement( wxT( "hole" ) );
3791  forEachIn( a2dVertexList, ( *iterp ).Get() )
3792  {
3793  if ( i % 6 == 0 )
3794  out.WriteNewLine();
3795  a2dLineSegment* seg = *iter;
3796  out.WriteStartElementAttributes( wxT( "xy" ) );
3797  out.WriteAttribute( wxT( "x" ), seg->m_x * out.GetScale() );
3798  out.WriteAttribute( wxT( "y" ), seg->m_y * out.GetScale() );
3799 
3800  if ( seg->GetArc() )
3801  {
3802  a2dArcSegment* arc = ( a2dArcSegment* ) seg;
3803  out.WriteAttribute( wxT( "xm" ), arc->m_x2 * out.GetScale() );
3804  out.WriteAttribute( wxT( "ym" ), arc->m_y2 * out.GetScale() );
3805  }
3806 
3807  out.WriteEndAttributes( true );
3808  i++;
3809  }
3810  out.WriteEndElement();
3811  }
3812 
3813  }
3814 }
3815 
3816 void a2dSurface::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
3817 {
3818  a2dPolygonL::DoLoad( parent, parser, xmlparts );
3819  if ( xmlparts == a2dXmlSer_attrib )
3820  {
3821  int holes = parser.GetAttributeValueBool( wxT( "holes" ), false );
3822  }
3823  else
3824  {
3825  while( parser.GetTagName() == wxT( "hole" ) )
3826  {
3827  a2dVertexListPtr holepoints = new a2dVertexList();
3828  parser.Next();
3829  while( parser.GetTagName() == wxT( "xy" ) )
3830  {
3831  double x = parser.GetAttributeValueDouble( wxT( "x" ) ) * parser.GetScale() ;
3832  double y = parser.GetAttributeValueDouble( wxT( "y" ) ) * parser.GetScale() ;
3833 
3834  a2dLineSegment* seg;
3835  if ( parser.HasAttribute( wxT( "xm" ) ) )
3836  {
3837  double xm = parser.GetAttributeValueDouble( wxT( "xm" ) ) * parser.GetScale() ;
3838  double ym = parser.GetAttributeValueDouble( wxT( "ym" ) ) * parser.GetScale() ;
3839 
3840  seg = new a2dArcSegment( x, y, xm, ym );
3841  }
3842  else
3843  seg = new a2dLineSegment( x, y );
3844 
3845  holepoints->push_back( seg );
3846 
3847  parser.Next();
3848  parser.Require( END_TAG, wxT( "xy" ) );
3849  parser.Next();
3850 
3851  }
3852  parser.Require( END_TAG, wxT( "hole" ) );
3853  parser.Next();
3854  AddHole( holepoints );
3855  }
3856  }
3857 }
3858 #endif //wxART2D_USE_CVGIO
3859 
3861 {
3862  double xh, yh;
3863  ic.GetInverseTransform().TransformPoint( hitEvent.m_x, hitEvent.m_y, xh, yh );
3864 
3865  a2dPoint2D P = a2dPoint2D( xh, yh );
3866  double pw = ic.GetWorldStrokeExtend();
3867  double margin = ic.GetTransformedHitMargin();
3868 
3869  unsigned int indexn = m_lsegments->size() + 1;
3870  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3871  {
3872  a2dVertexListPtr vlist = ( *iterp );
3873  hitEvent.m_how = vlist->HitTestPolygon( P, margin );
3874  if ( hitEvent.m_how.IsHit() )
3875  {
3876  hitEvent.m_how.m_index += indexn;
3877  return true;
3878  }
3879  indexn += vlist->size();
3880  indexn++; // dummy index for end
3881  }
3882  if ( !hitEvent.m_how.IsHit() )
3883  hitEvent.m_how = PointInPolygon( P, pw + margin );
3884  return hitEvent.m_how.IsHit();
3885 }
3886 
3887 bool a2dSurface::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
3888 {
3889  a2dPolygonL::DoStartEdit( editmode, editstyle );
3890  if ( m_flags.m_editable )
3891  {
3892  if ( editmode == 1 )
3893  {
3894  if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
3895  {
3896  m_flags.m_visiblechilds = true;
3898  a2dSurface* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSurface );
3899 
3900  //add properties and handles as children in order to edit the object.
3901  int index = 0;
3902  a2dListOfa2dVertexList::const_iterator iterporg = original->m_holes.begin();
3903  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
3904  {
3905  a2dVertexListPtr vlist = ( *iterp );
3906  a2dVertexListPtr vlistorg = ( *iterporg );
3907  a2dVertexList::iterator iter = vlist->begin();
3908  a2dVertexList::iterator iterorg = vlistorg->begin();
3909  a2dLineSegment* seg;
3910  a2dLineSegment* nextseg;
3911  while ( iter != vlist->end() )
3912  {
3913  seg = ( *iter );
3914  iter++;
3915  if ( iter != vlist->end() )
3916  nextseg = ( *iter );
3917  else
3918  nextseg = vlist->front();
3919  iter--;
3920 
3921  //not inclusive matrix so relative to polygon
3922  a2dPolyHandleL* handle = new a2dPolyHandleL( this, iter, iterorg, vlist, vlistorg, wxT( "__indexhole__" ) );
3923  Append( handle );
3924  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
3925  handle->SetLayer( m_layer );
3926  if ( seg->GetArc() )
3927  {
3928  // todo split in line segments ( maybe under certain conditions of matrix not?? ).
3929  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
3930 
3931  handle = new a2dPolyHandleL( this, iter, iterorg, vlist, vlistorg, cseg->m_x2, cseg->m_y2, wxT( "__indexhole_arc__" ) );
3932  handle->SetLayer( m_layer );
3933  Append( handle );
3934  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
3935  }
3936  index++;
3937  iter++;
3938  iterorg++;
3939  }
3940  iterporg++;
3941  }
3942 
3943  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dPolyHandleL" ) );
3944  m_flags.m_editingCopy = true;
3945 
3946  //calculate bbox's elase mouse events may take place when first idle event is not yet
3947  //processed to do this calculation.
3949  //stil set it pending to do the redraw ( in place )
3950  SetPending( true );
3951  }
3952  return true;
3953  }
3954  else
3955  {
3956  PROPID_Allowrotation->SetPropertyToObject( this, true );
3957  PROPID_Allowskew->SetPropertyToObject( this, true );
3958 
3959  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
3960  }
3961  }
3962 
3963  return false;
3964 }
3965 
3966 void a2dSurface::OnCanvasObjectMouseEvent( a2dCanvasObjectMouseEvent& event )
3967 {
3969  {
3970  event.Skip();
3971  return;
3972  }
3973 
3974  a2dIterC* ic = event.GetIterC();
3975 
3976  a2dPolyHandleL* seghandle;
3977 
3978  double xw, yw;
3979  xw = event.GetX();
3980  yw = event.GetY();
3981 
3982  a2dSurface* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dSurface );
3983 
3984  if ( event.GetMouseEvent().LeftDown() )
3985  {
3986  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
3987  if ( restrictEngine )
3988  restrictEngine->SetRestrictPoint( xw, yw );
3989 
3990  if ( event.GetHow().IsEdgeHit() )
3991  {
3992  int index = event.GetHow().m_index;
3993  a2dVertexList::iterator iterSeg = GetSegmentAtIndex( index );
3994  a2dVertexList::iterator iterSegOrg = original->GetSegmentAtIndex( index );
3995  a2dVertexList* vlist = GetSegmentListAtIndex( index );
3996  if ( vlist == m_lsegments )
3997  {
3998  event.Skip();
3999  return;
4000  }
4001  a2dVertexList* vlistorg = original->GetSegmentListAtIndex( index );
4002 
4003  if ( event.GetMouseEvent().AltDown() )
4004  seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, vlist, vlistorg, wxT( "__inserthole__" ) );
4005  else
4006  seghandle = new a2dPolyHandleL( this, iterSeg, iterSegOrg, vlist, vlistorg, wxT( "__segmenthole__" ) );
4007  seghandle->SetLayer( m_layer );
4008  Append( seghandle );
4009  seghandle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
4010 
4011  //canvas mouse events arrive without the polygon matrix included.
4012  a2dIterCU polygoncontext( *ic, this );
4013  a2dIterCU handlecontext( *ic, seghandle );
4014  seghandle->ProcessEvent( event );
4015  }
4016  else
4017  event.Skip();
4018  }
4019  else
4020  event.Skip();
4021 }
4022 
4023 void a2dSurface::OnHandleEvent( a2dHandleMouseEvent& event )
4024 {
4025  a2dIterC* ic = event.GetIterC();
4026 
4027  if ( event.GetCanvasHandle()->GetRelease() )
4028  return;
4029 
4030  if ( m_flags.m_editingCopy )
4031  {
4032  a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
4033  if ( draghandle->GetName() != wxT( "__indexhole__" ) &&
4034  draghandle->GetName() != wxT( "__indexhole_arc__" ) &&
4035  draghandle->GetName() != wxT( "__inserthole__" ) &&
4036  draghandle->GetName() != wxT( "__segmenthole__" )
4037  )
4038  {
4039  event.Skip(); //maybe on the base class handles
4040  return;
4041  }
4042 
4043  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
4044  wxUint16 editmode = PROPID_Editmode->GetPropertyValue( this );
4045 
4046  if ( editmode == 1 )
4047  {
4048  double xw, yw;
4049  xw = event.GetX();
4050  yw = event.GetY();
4051  a2dAffineMatrix atWorld = ic->GetTransform();
4052 
4053  //we need to get the matrix until the parent of the a2dPolyHandleL,
4054  // and not inclusif the handle itself.
4055  //and therefore apply inverted handle matrix.
4056  a2dAffineMatrix inverselocal = m_lworld;
4057  inverselocal.Invert();
4058 
4060 
4061  double xinternal, yinternal;
4062  inverse.TransformPoint( xw, yw, xinternal, yinternal );
4063 
4064  a2dPolyHandleL* draghandle = wxDynamicCast( event.GetCanvasHandle(), a2dPolyHandleL );
4065  a2dVertexListPtr holevlist = draghandle->GetSegments();
4066  a2dVertexListPtr holevlistorg = draghandle->GetSegmentsOrg();
4067 
4068 
4069  a2dLineSegment* segment = *( draghandle->GetNode() );
4070  a2dLineSegment* nextsegment = *( holevlist->GetNextAround( draghandle->GetNode() ) );
4071  a2dLineSegment* segmentorg = *( draghandle->GetNodeOrg() );
4072  a2dLineSegment* nextsegmentorg = *( holevlistorg->GetNextAround( draghandle->GetNodeOrg() ) );
4073 
4074  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
4075 
4076  double xwi;
4077  double ywi;
4078  if( m_flags.m_snap )
4079  {
4080  if ( restrictEngine )
4081  restrictEngine->RestrictPoint( xinternal, yinternal );
4082  }
4083  inverselocal.TransformPoint( xinternal, yinternal, xwi, ywi );
4084  a2dAffineMatrix origworld = m_lworld;
4085 
4086  if ( draghandle->GetName() == wxT( "__indexhole__" ) )
4087  {
4088  if ( event.GetMouseEvent().ControlDown() && event.GetMouseEvent().LeftDown() )
4089  {
4090  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentorg ) );
4091  double x, y;
4092  RemoveSegment( x, y, segment );
4093  ReleaseChild( draghandle );
4094 
4095  // the handle generated this event in LeftDown, But before LeftUp event the
4096  // restart is already done, getting rid of handle.
4097  // So do set context right here.
4098  ic->SetCorridorPathToParent();
4099  ic->GetDrawingPart()->PopCursor();
4100  }
4101  if ( event.GetMouseEvent().LeftUp() )
4102  {
4103  double x, y;
4104  x = segment->m_x; y = segment->m_y;
4105  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x, y, segmentorg, false ) );
4106  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x, y, index );
4107  draghandle->SetPosXY( x, y );
4108  //Klaas (code not good, handles are used and removed at same time )
4109  //RemoveRedundantPoints( original );
4110  original->AdjustAfterChange( true );
4111  }
4112  else if ( event.GetMouseEvent().Dragging() )
4113  {
4114  //wxLogDebug( _("Dragging %d"), index);
4115  segment->m_x = xwi;
4116  segment->m_y = ywi;
4117  SetPending( true );
4118  draghandle->SetPosXY( xwi, ywi );
4119  SetPosXYSegment( segmentorg, xwi, ywi, false );
4120  AdjustAfterChange( false );
4121  }
4122  }
4123  else if ( draghandle->GetName() == wxT( "__indexhole_arc__" ) )
4124  {
4125  a2dArcSegment* csegment = ( a2dArcSegment* ) segment;
4126  a2dArcSegment* csegmentorg = ( a2dArcSegment* ) segmentorg;
4127  if ( event.GetMouseEvent().LeftUp() )
4128  {
4129  double x, y;
4130  x = csegment->m_x2; y = csegment->m_y2;
4131  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveMidSegment( original, x, y, csegmentorg, false ) );
4132  //a2dDocviewGlobals->RecordF( this, wxT("movearcmidpoint %f %f %d"), x, y, index );
4133  draghandle->SetPosXY( x, y );
4134  //Klaas (code not good, handles are used and removed at same time )
4135  //RemoveRedundantPoints( original );
4136  original->AdjustAfterChange( true );
4137  }
4138  else if ( event.GetMouseEvent().Dragging() )
4139  {
4140  csegment->m_x2 = xwi; csegment->m_y2 = ywi;
4141  SetPending( true );
4142  //csegment->SetMidPoint( *prevsegment, xwi, ywi );
4143  //wxLogDebug( _("Dragging %d"), index);
4144  draghandle->SetPosXYRestrict( xwi, ywi );
4145  SyncHandlesWithLineSegments();
4146  AdjustAfterChange( false );
4147  }
4148  else
4149  event.Skip(); //maybe on the base class handles
4150  }
4151  else if ( draghandle->GetName() == wxT( "__inserthole__" ) )
4152  {
4153  // The index is the segment index. The index of the new point is 1 larger
4154  // than the segment index.
4155  if ( event.GetMouseEvent().LeftUp() )
4156  {
4157  double x, y;
4158  x = nextsegment->m_x;
4159  y = nextsegment->m_y;
4160  m_root->GetCommandProcessor()->Submit( new a2dCommand_AddPoint( original, x, y, nextsegmentorg, false ) );
4161  // !!!!???? how to do this ????!!!!
4162  // a2dDocviewGlobals->RecordF( this, wxT("addpoint %f %f %d"), x, y, index+1 );
4163  draghandle->SetPosXY( x, y );
4164  original->AdjustAfterChange( true );
4165  }
4166  else if ( event.GetMouseEvent().LeftDown() )
4167  {
4168  AddPoint( xwi, ywi, nextsegment, false );
4169  draghandle->SetPosXYRestrict( xwi, ywi );
4170  AdjustAfterChange( false );
4171  }
4172  else if ( event.GetMouseEvent().Dragging() )
4173  {
4174  SetPosXYSegment( nextsegment, xwi, ywi , false );
4175  draghandle->SetPosXYRestrict( xwi, ywi );
4176  AdjustAfterChange( false );
4177  }
4178  else
4179  event.Skip(); //maybe on the base class handles
4180  }
4181  else if ( draghandle->GetName() == wxT( "__segmenthole__" ) )
4182  {
4183  if ( event.GetMouseEvent().LeftUp() )
4184  {
4185  double x1, y1;
4186  double x2, y2;
4187  x1 = segment->m_x;
4188  y1 = segment->m_y;
4189 
4190  x2 = nextsegment->m_x;
4191  y2 = nextsegment->m_y;
4192 
4193  double xwi, ywi, dx, dy;
4194  dx = 0.5 * ( x2 - x1 );
4195  dy = 0.5 * ( y2 - y1 );
4196  xwi = x1 + dx;
4197  ywi = y1 + dy;
4198  draghandle->SetPosXYRestrict( xwi, ywi );
4199  x1 = xwi - dx; x2 = xwi + dx;
4200  y1 = ywi - dy; y2 = ywi + dy;
4201 
4202  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, x1, y1, segmentorg, false ) );
4204  new a2dCommand_MoveSegment( original, x2, y2, nextsegmentorg, false ) );
4205 
4206  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x1, y1, index );
4207  //a2dDocviewGlobals->RecordF( this, wxT("movepoint %f %f %d"), x2, y2, index+1 );
4208 
4209 
4210  //Klaas (code not good, handles are used and removed at same time )
4211  //RemoveRedundantPoints( original );
4212  //
4213  SyncHandlesWithLineSegments();
4214 
4215 
4216  // handles called "__segment__" are temporary handles, can be removed after drag
4217  m_childobjects->Release( a2dCanvasOFlags::ALL, wxT( "a2dPolyHandleL" ), NULL, wxT( "__segmenthole__" ), false );
4218  original->AdjustAfterChange( true );
4219  }
4220  else if ( event.GetMouseEvent().LeftDown() )
4221  {
4222  // set the initial handle coordinates
4223  a2dPolyHandleL::PROPID_tmpXIH->SetPropertyToObject( draghandle, xwi );
4224  a2dPolyHandleL::PROPID_tmpYIH->SetPropertyToObject( draghandle, ywi );
4225  // set the initial vertex coordinates
4226  double x, y;
4227  x = segment->m_x;
4228  y = segment->m_y;
4229  a2dPolyHandleL::PROPID_tmpXIV1->SetPropertyToObject( draghandle, x );
4230  a2dPolyHandleL::PROPID_tmpYIV1->SetPropertyToObject( draghandle, y );
4231  x = nextsegment->m_x;
4232  y = nextsegment->m_y;
4233  a2dPolyHandleL::PROPID_tmpXIV2->SetPropertyToObject( draghandle, x );
4234  a2dPolyHandleL::PROPID_tmpYIV2->SetPropertyToObject( draghandle, y );
4235  }
4236  else if ( event.GetMouseEvent().Dragging() )
4237  {
4238  draghandle->m_dragging = true;
4239 
4240  double xi_h = a2dPolyHandleL::PROPID_tmpXIH->GetPropertyValue( draghandle );
4241  double yi_h = a2dPolyHandleL::PROPID_tmpYIH->GetPropertyValue( draghandle );
4242  double xi_v1 = a2dPolyHandleL::PROPID_tmpXIV1->GetPropertyValue( draghandle );
4243  double yi_v1 = a2dPolyHandleL::PROPID_tmpYIV1->GetPropertyValue( draghandle );
4244  double xi_v2 = a2dPolyHandleL::PROPID_tmpXIV2->GetPropertyValue( draghandle );
4245  double yi_v2 = a2dPolyHandleL::PROPID_tmpYIV2->GetPropertyValue( draghandle );
4246 
4247  //wxASSERT( xi_h && yi_h && xi_v1 && yi_v1 && xi_v2 && yi_v2 );
4248 
4249  if( m_flags.m_snap )
4250  {
4251  // snap vertex 1 of segment.
4252  double x, y, dx, dy;
4253 
4254  dx = xi_v1 - xi_h;
4255  dy = yi_v1 - yi_h;
4256  x = xwi + dx;
4257  y = ywi + dy;
4258  a2dRestrictionEngine* restrictEngine = GetHabitat()->GetRestrictionEngine();
4259  if ( restrictEngine )
4260  restrictEngine->RestrictPoint( x, y );
4261  xwi = x - dx;
4262  ywi = y - dy;
4263  }
4264  draghandle->SetPosXY( xwi, ywi );
4265  double x1 = xi_v1 - xi_h + xwi;
4266  double y1 = yi_v1 - yi_h + ywi;
4267  double x2 = xi_v2 - xi_h + xwi;
4268  double y2 = yi_v2 - yi_h + ywi;
4269 
4270  segment->m_x = x1;
4271  segment->m_y = y1;
4272  nextsegment->m_x = x2;
4273  nextsegment->m_y = y2;
4274 
4275  SetPending( true );
4276  AdjustAfterChange( false );
4277  }
4278  else
4279  event.Skip(); //maybe on the base class handles
4280  }
4281  else
4282  event.Skip(); //maybe the base class handles
4283  }
4284  else
4285  event.Skip();
4286  }
4287  else
4288  {
4289  event.Skip();
4290  }
4291 }
4292 
4293 void a2dSurface::SetHandleToIndex( a2dPolyHandleL* handle, unsigned int index )
4294 {
4295  handle->SetNode( GetSegmentAtIndex( index ) );
4296  a2dPolygonL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dPolygonL );
4297  handle->SetNodeOrg( original->GetSegmentAtIndex( index ) );
4298 }
4299 
4300 int a2dSurface::GetIndexSegment( a2dLineSegmentPtr seg )
4301 {
4302  int index = -1;
4303  if ( seg.Get() == NULL )
4304  {
4305  if ( !m_lsegments->empty() )
4306  return m_lsegments->IndexOf( m_lsegments->back() );
4307  return -1;
4308  }
4309 
4310  index = m_lsegments->IndexOf( seg );
4311  if ( index != -1 )
4312  return index;
4313 
4314  index = m_lsegments->size();
4315  index++;
4316  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4317  {
4318  a2dVertexListPtr vlist = ( *iterp );
4319  a2dVertexList::iterator iter = vlist->begin();
4320  while ( iter != vlist->end() )
4321  {
4322  if ( *iter == seg )
4323  {
4324  return index;
4325  }
4326  index++;
4327  iter++;
4328  }
4329  index++; // dummy index for ends
4330  }
4331  return -1;
4332 }
4333 
4334 a2dVertexList::iterator a2dSurface::GetSegmentAtIndex( unsigned int index )
4335 {
4336  if ( index < m_lsegments->size() + 1 )
4337  {
4338  return m_lsegments->item( index );
4339  }
4340  unsigned int indexn = m_lsegments->size();
4341  indexn++;
4342  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4343  {
4344  a2dVertexListPtr vlist = ( *iterp );
4345  a2dVertexList::iterator iter = vlist->begin();
4346  while ( iter != vlist->end() )
4347  {
4348  if ( indexn == index )
4349  {
4350  return iter;
4351  }
4352  indexn++;
4353  iter++;
4354  }
4355  if( indexn == index )
4356  {
4357  return iter;
4358  }
4359  indexn++; // dummy index for end
4360  }
4361  return m_lsegments->end();
4362 }
4363 
4364 a2dVertexList* a2dSurface::GetSegmentListAtIndex( unsigned int index )
4365 {
4366  if ( index < m_lsegments->size() + 1 )
4367  {
4368  return m_lsegments;
4369  }
4370  unsigned int indexn = m_lsegments->size();
4371  indexn++;
4372  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4373  {
4374  a2dVertexListPtr vlist = ( *iterp );
4375  a2dVertexList::iterator iter = vlist->begin();
4376  while ( iter != vlist->end() )
4377  {
4378  if ( indexn == index )
4379  {
4380  return vlist;
4381  }
4382  indexn++;
4383  iter++;
4384  }
4385  if( indexn == index )
4386  {
4387  return vlist;
4388  }
4389  indexn++; // dummy index for end
4390  }
4391  return NULL;
4392 }
4393 
4394 
4395 void a2dSurface::RemoveSegment( double& x, double& y , a2dLineSegmentPtr seg, bool transformed )
4396 {
4397  if ( seg.Get() == NULL )
4398  {
4399  a2dLineSegment* point;
4400  point = m_lsegments->back();
4401  x = point->m_x;
4402  y = point->m_y;
4403  m_lsegments->pop_back();
4404  }
4405  else
4406  {
4407  a2dVertexList::iterator iter = m_lsegments->begin();
4408  a2dLineSegment* point;
4409  while ( iter != m_lsegments->end() )
4410  {
4411  if ( *iter == seg )
4412  {
4413  point = ( *iter );
4414  x = point->m_x;
4415  y = point->m_y;
4416  m_lsegments->erase( iter );
4417  break;
4418  }
4419  iter++;
4420  }
4421  }
4422 
4423  a2dLineSegment* point;
4424  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4425  {
4426  a2dVertexListPtr vlist = ( *iterp );
4427  a2dVertexList::iterator iter = vlist->begin();
4428  while ( iter != vlist->end() )
4429  {
4430  if ( *iter == seg )
4431  {
4432  point = ( *iter );
4433  x = point->m_x;
4434  y = point->m_y;
4435  vlist->erase( iter );
4436  break;
4437  }
4438  iter++;
4439  }
4440  }
4441 
4442  if ( transformed )
4443  {
4444  m_lworld.TransformPoint( x, y, x, y );
4445  }
4446 
4447  SetPending( true );
4448 }
4449 
4450 void a2dSurface::InsertSegment( unsigned int index, a2dLineSegmentPtr segin )
4451 {
4452  if ( index < m_lsegments->size() + 1 )
4453  {
4454  m_lsegments->Insert( index, segin );
4455  return;
4456  }
4457  unsigned int indexn = m_lsegments->size();
4458  indexn++;
4459  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4460  {
4461  a2dVertexListPtr vlist = ( *iterp );
4462  a2dVertexList::iterator iter = vlist->begin();
4463  while ( iter != vlist->end() )
4464  {
4465  if ( indexn == index )
4466  {
4467  vlist->insert( iter, segin );
4468  return;
4469  }
4470  indexn++;
4471  iter++;
4472  }
4473  if( indexn == index )
4474  {
4475  vlist->insert( iter, segin );
4476  return;
4477  }
4478  indexn++; // dummy index for end
4479  }
4480 
4481 }
4482 
4483 void a2dSurface::GetPosXYSegment( a2dLineSegmentPtr seg, double& x, double& y, bool transform ) const
4484 {
4485  if ( seg.Get() == NULL )
4486  {
4487  a2dLineSegment* point;
4488  point = m_lsegments->back();
4489  x = point->m_x;
4490  y = point->m_y;
4491  }
4492  else
4493  {
4494  x = seg->m_x;
4495  y = seg->m_y;
4496  }
4497 
4498  if ( transform )
4499  {
4500  m_lworld.TransformPoint( x, y, x, y );
4501  }
4502 }
4503 
4504 void a2dSurface::SetPosXYSegment( a2dLineSegmentPtr seg, double x, double y, bool afterinversion )
4505 {
4506  if ( afterinversion )
4507  {
4508  a2dAffineMatrix inverse = m_lworld;
4509  inverse.Invert();
4510  inverse.TransformPoint( x, y, x, y );
4511  }
4512 
4513  m_lsegments->SetPointAdjustArcs( seg, x, y, true );
4514 
4515  for( a2dListOfa2dVertexList::const_iterator iterp = m_holes.begin(); iterp != m_holes.end(); iterp++ )
4516  {
4517  a2dVertexListPtr vlist = ( *iterp );
4518  vlist->SetPointAdjustArcs( seg, x, y, true );
4519  }
4520 
4521  SetPending( true );
4522 }
a2dHit m_how
return in which way the object was hit (stroke, fill, ...)
Definition: canobj.h:301
a2dPin * FindNonWirePin(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL)
Definition: canpin.cpp:1012
void SetClippingFromBox(a2dBoundingBox &bbox=wxNonValidBbox)
set the clipping polygon according to the given box
Definition: polygon.cpp:3233
void PushCursor(const wxCursor &cursor)
push a cursor on the cursor stack, and set display cursor to new back being cursor.
Definition: drawer.cpp:1052
bool GetAttributeValueBool(const wxString &attrib, bool defaultv=false)
Returns the boolean value of an attribute.
Definition: genxmlpars.cpp:537
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
bool IsStrokeHit() const
true if this is a stroke hit (parent or child/member stroke)
Definition: polyver.h:109
used to move points in polygon objects
Definition: drawing.h:1997
double m_relx
(world coordinates) hit point x relative to the canvas object its parent object(s) ...
Definition: canobj.h:289
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: polygon.cpp:3778
virtual void Render(a2dIterC &ic, OVERLAP clipparent)
Render this object to the active a2dDrawingPart.
Definition: canobj.cpp:4712
used to move points in polygon objects
Definition: drawing.h:2033
double GetAbsY() const
get absolute Y position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:966
bool SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which, const wxString &classname=wxT(""), a2dCanvasObjectFlagsMask whichobjects=a2dCanvasOFlags::ALL, const a2dBoundingBox &bbox=wxNonValidBbox, const a2dAffineMatrix &tworld=a2dIDENTITY_MATRIX)
set all given bit flags at once recursive for all objects in given boundingbox
Definition: objlist.cpp:519
void RemoveSegment(double &x, double &y, a2dLineSegmentPtr seg=NULL, bool transformed=true)
removes point at index
Definition: polygon.cpp:4395
all basic primitives derived from a2dCanvasObject
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
Base class for all types of strokes, understood by a2dDrawer2D classes.
Definition: stylebase.h:378
void SetRoot(a2dDrawing *root, bool recurse=true)
Sets this object to a a2dCanvasDocument.
Definition: canobj.cpp:5933
unsigned int m_index
For edge/vertex hits the index of the edge / vertex.
Definition: polyver.h:89
bool IsNoStroke() const
Definition: stylebase.h:510
bool GetGeneratePins() const
get the GeneratePins flag
Definition: canobj.h:2289
a2dVertexList * GetSegmentsOrg()
get to segments chain to which this handle belongs in the original ( not edit copy ) ...
Definition: polygon.h:784
a2dObject * LoadOneObject(wxObject *parent)
load one object from a CVG file.
bool HasAttribute(const wxString &attrib)
Does the current tag have this attribute?
Definition: genxmlpars.cpp:560
virtual double Length(const a2dLineSegment &prev)
calculate length
Definition: polyver.cpp:256
a2dHandle is used inside editing versions of a certain objects.
Definition: canpin.h:30
mouse event sent from a2dCanvasObject to itself
Definition: canglob.h:223
a2dVpath * ConvertToVpath(bool arc, bool closed=false)
return converted vector Vpath, arc segments stay intact if arc is true
Definition: polyver.cpp:2068
a2dConnectTask
flags for searching a connecting a2dpinClass, for the connecting task at hand.
Definition: connectgen.h:40
bool FindNearPoint(const a2dAffineMatrix *cworld, double xIn, double yIn, double *xOut, double *yOut)
Find the point on the polyline closest to the given world point.
Definition: polygon.cpp:2870
void Set(double xs, double ys, double xm, double ym, double xe, double ye)
set arc using begin, end and middle point.
Definition: canprim.cpp:3012
virtual void PopTransform(void)
Recall the previously saved user-to-world transform off the matrix stack.
Definition: drawer2d.cpp:480
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
void SetRelease(bool value)
set release flag
Definition: gen.h:1346
XMLeventType Next()
Walks to next element and returns event type.
Definition: genxmlpars.cpp:422
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: polygon.cpp:244
bool ResolveOrAdd(a2dSmrtPtr< a2dObject > *storedHere, const wxString &id=wxT(""))
try to resolve the object that is in storedHere when it is a reference.
Definition: gen.cpp:4760
void ConvertToLines(double aberation=0)
Convert complex segments to line segments.
Definition: polyver.cpp:1948
void SetClippingTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Set the matrix used for the clipping polygon.
Definition: polygon.cpp:3299
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
void SetName(const wxString &name)
set the name of the handle (must be unique)
Definition: canpin.h:59
a2dPin * FindEndPin()
Get the end pin from the childs.
Definition: polygon.cpp:3035
a2dDrawing * m_root
root group for rendering and accessing the canvas&#39;s also contains layer settings
Definition: canobj.h:2525
a2dCanvasOFlags m_flags
holds flags for objects
Definition: canobj.h:2528
void Render(a2dIterC &ic, OVERLAP clipparent)
Render this object to the active a2dDrawingPart.
Definition: polygon.cpp:3341
static const long sm_PinCanConnectToPinClass
Pin can connect to supplied a2dPinClass.
Definition: canpin.h:505
const a2dAffineMatrix & GetInverseTransform() const
Inverse of GetTransform()
Definition: canobj.cpp:699
static const a2dCanvasObjectFlagsMask BIN2
Definition: candefs.h:193
#define EVT_CANVASOBJECT_ENTER_EVENT(func)
static event table macro for a2dCanvasObject mouse enter event
Definition: canglob.h:314
void Transform(const a2dAffineMatrix &world)
transform all segments with given matrix
Definition: polyver.cpp:4075
a2dVertexList * GetSegments()
get to segments chain to which this handle belongs in the original ( not edit copy ) ...
Definition: polygon.h:781
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
This is a class/type description for a2dPin&#39;s.
Definition: canpin.h:628
void WriteStartElementAttributes(const wxString &name, bool newLine=true)
Writes start tag which has attributes.
Definition: genxmlpars.cpp:757
polygon defined with list of points.
Definition: polygon.h:45
used to add points to polygon objects
Definition: drawing.h:1959
void GetPosXYSegment(a2dLineSegmentPtr seg, double &x, double &y, bool transform=true) const
get point x and y at index
Definition: polygon.cpp:4483
Ref Counted base object.
Definition: gen.h:1045
bool Rotate(double angle)
Rotate clockwise by the given number of degrees:
Definition: afmatrix.cpp:432
a2dPATH_END_TYPE m_pathtype
when m_contourwidth != 0 what is the end of the line looking like.
Definition: polygon.h:481
snap segments of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:120
void Enlarge(const double Marge)
enlarge with the given amount
Definition: bbox.cpp:162
void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: polygon.cpp:2570
double m_contourwidth
if != 0 the polygon is contoured at distance m_contourwidth/2
Definition: polygon.h:307
virtual void SetContourWidth(double width)
set the Contour width of the shape
Definition: canobj.h:1408
clips all children to a polygon
Definition: polygon.h:676
basetype * GetPropertyValuePtr(a2dObject *obj) const
Get a pointer to the property value in obj.
Definition: id.inl:366
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: polygon.cpp:3690
a2dBoundingBox GetBbox(const a2dAffineMatrix &lworld=a2dIDENTITY_MATRIX)
return a boundingbox of a transformed vertexarray
Definition: polyver.cpp:2581
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: polygon.cpp:3291
void SetHandleToIndex(a2dPolyHandleL *handle, unsigned int index)
a handle in editing is updated to a segment at index given
Definition: polygon.cpp:4293
bool IsHit() const
true if this is a hit
Definition: polyver.h:107
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: canobj.cpp:5149
used to connect two pins
Definition: drawing.h:2411
double PointDistance(const a2dPoint2D &p, a2dPoint2D *nearest) const
Calculate the distance of a point from the line. Works even if l==0.
Definition: liner.cpp:657
Arc Segment.
Definition: polyver.h:1112
#define EVT_CANVASHANDLE_MOUSE_EVENT(func)
static event table macro for a2dHandle mouse event
Definition: canglob.h:318
void SetDrawerStroke(const a2dStroke &stroke)
Used to set the current stroke.
Definition: drawer2d.cpp:565
#define EVT_CANVASHANDLE_MOUSE_EVENT_LEAVE(func)
static event table macro for a2dHandle mouse leave event
Definition: canglob.h:322
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
virtual void DrawPolygon(a2dVertexArray *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
Draw polygon in world coordinates using pointarray.
Definition: drawer2d.cpp:1889
UpdateMode
Various mode flags for Update.
Definition: canobj.h:1091
double m_x2
x2 x of arc midpoint
Definition: polyver.h:471
void SetChord(bool chord)
if true draw as a chord ( no fill end no lines to center )
Definition: canprim.cpp:3006
double GetScale()
See GetScale()
Definition: genxmlpars.h:784
snap to pins in other objects when not connected
Definition: restrict.h:112
void SetStrokeWorldExtend(double worldStrokeExtend)
Set strokeworld extend of last added object, used in a2dCanvasObject::DoIsHitWorld() ...
Definition: canobj.h:3400
bool GetPixelStroke() const
if the width is pixels or not.
Definition: stylebase.cpp:6335
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
OVERLAP
Result of a a2dBoundingBox intersection or hittest.
Definition: bbox.h:24
bool m_visiblechilds
child objects are visible or not
Definition: candefs.h:292
void RemoveRedundantPoints(a2dCanvasObject *sendCommandsTo=NULL)
remove all points that are redundant
Definition: polygon.cpp:2022
a2dGlobal * a2dGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: artglob.cpp:34
void Clear()
Remove and delete all points in the polygon.
Definition: polygon.cpp:95
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
bool m_hasPins
true if this object does have a2dPin&#39;s as children
Definition: candefs.h:323
The base class for all drawable objects in a a2dCanvasDocument.
virtual bool GeneratePins(a2dPinClass *toConnectTo, a2dConnectTask task, double x, double y, double margin=0)
Definition: polygon.cpp:2817
bool m_dragging
indicates dragging was/is going on
Definition: polygon.h:794
double GetTransformedHitMargin()
transformed to object its coordinate system
Definition: canobj.cpp:616
a2dVertexList * ConvertSplinedPolyline(double Aber) const
Spline conversion for polyline.
Definition: polyver.cpp:2858
a2dPolygonLClipper(a2dBoundingBox &bbox=wxNonValidBbox)
construct the clipping polygon according to the given box
Definition: polygon.cpp:3210
Arc Segment in a2dVertexList.
Definition: polyver.h:371
wxUint16 m_layer
layer of object, default wxLAYER_DEFAULT
Definition: canobj.h:2556
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: canobj.cpp:5728
void ReStoreFixedStyle()
when fixed drawing style is set, it can be overruled.
Definition: drawer2d.cpp:711
vertex array of line and arc segments.
Definition: polyver.h:494
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dPin * FindPin(int *i)
Get all pins one by one. i is updated by this function.
Definition: polygon.cpp:3040
a2dBoundingBox wxNonValidBbox
global non valid boundingbox to use as default argument etc.
Definition: bbox.cpp:23
virtual a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
when implemented the object without its children, is converted to
Definition: polygon.cpp:3584
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dDerivedCanvasObjectStart
id for a2dWalkEvent issued from within a2dWalkerIOHandler
a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
clone it
Definition: polygon.cpp:3459
bool SetPointIfCloser(const a2dPoint2D &pointToSnapTo, const a2dPoint2D &pointToSnap, a2dPoint2D &bestPointSofar, double thresHoldWorld)
Definition: canobj.cpp:4189
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: polygon.cpp:2309
void ReStartEdit(wxUint16 editmode)
to restart editing in a different mode
Definition: canobj.cpp:1693
a2dLayers * GetLayerSetup()
Get the layersettings for the canvas.
Definition: drawing.h:506
vertex list of line and arc segments.
Definition: polyver.h:600
void TransformPoint(double x, double y, double &tx, double &ty) const
Transform a point.
Definition: afmatrix.cpp:559
bool m_snap_to
snapping of other objects to this when in place
Definition: candefs.h:283
handle holds a pointer to a polygon/polyline segment
Definition: polygon.h:713
wxString GetName() const
get the name given to the handle.
Definition: canpin.h:56
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: polygon.cpp:1544
bool GetSelected() const
is the object selected flag set
Definition: canobj.h:1603
void SetSelected(bool selected)
Set the object selected flag if allowed.
Definition: canobj.h:1620
virtual bool RestrictToObject(a2dIterC &ic, const a2dPoint2D &pointToSnapTo, a2dPoint2D &bestPointSofar, a2dSnapToWhatMask snapToWhat, double thresHoldWorld)
called from an a2dRestrictionEngine, to restrict vertexes, lines, object to this object.
Definition: canobj.cpp:4209
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: polygon.cpp:869
void WriteEndElement(bool newLine=true)
Writes correspondending end tag for the current start tag.
Definition: genxmlpars.cpp:862
a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
when implemented the object without its children, is converted to
Definition: polygon.cpp:133
virtual a2dVertexList * GetAsVertexList(bool &returnIsPolygon) const
convert to a polygon.
Definition: polygon.cpp:1853
void SetContourWidth(double width)
set the Contour width of the shape
Definition: polygon.h:237
int ReleaseChild(a2dCanvasObject *obj, bool backwards=false, bool all=false, bool now=false, bool undoCommands=false)
remove the given object from the childobjects
Definition: canobj.cpp:6260
bool FindNearPointOrtho(const a2dAffineMatrix *cworld, double xIn, double yIn, double *xOut, double *yOut)
Find the point on the polyline that is the closest orthogonal projection to the given world point...
Definition: polygon.cpp:2930
int FindPinSegmentIndex(a2dPin *pinToFind, double margin=a2dACCUR)
find the index of the segment where the pin is on.
Definition: polygon.cpp:3074
a2dAffineMatrix m_lworld
used for positioning the object (x,y,ang,scale etc.)
Definition: canobj.h:2559
void SetClose(a2dPATHSEG_END close)
set this segment is closing a part since the last move
Definition: polyver.h:913
a2dPolyHandleL()
constructor
Definition: polygon.cpp:3407
void SetDrawerFill(const a2dFill &fill)
Used to set the current fill.
Definition: drawer2d.cpp:621
bool m_generatePins
generate pins if true
Definition: candefs.h:268
~a2dPolygonLClipper()
destructor
Definition: polygon.cpp:3229
Io handler to iterate through a a2dDocument.
Definition: gen.h:3911
#define EVT_CANVASHANDLE_MOUSE_EVENT_ENTER(func)
static event table macro for a2dHandle mouse enter event
Definition: canglob.h:320
bool MoveDynamicPinCloseTo(a2dPin *pin, const a2dPoint2D &point, bool final)
Move the given dynamic pin close to the given absolute point.
Definition: polygon.cpp:2993
bool SetPosXYRestrict(double &x, double &y)
set position to x,y but restricted, returns new values
Definition: canobj.cpp:1606
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dHandle
Definition: canglob.h:290
bool GetCheck() const
general flag use at will.
Definition: gen.h:1342
virtual a2dCanvasObjectList * GetAsPolylines(bool transform=true) const
convert contour to a polyline and holes to seperate polylines.
Definition: polygon.cpp:3550
snap to other objects its vertexes, which are decided in a2dCanvasObject::RestrictToObject() ...
Definition: restrict.h:116
wxUint32 m_option
the way to hit/traverse the document.
Definition: canobj.h:299
void WriteNewLine()
Writes a new line and takes care of indentation.
Definition: genxmlpars.cpp:890
void SetIgnoreSetpending(bool value=true)
set IgnoreSetpending flag
Definition: canobj.h:2299
bool IsEdgeHit() const
true if this is a stroke hit on an edge
Definition: polyver.h:128
~a2dPolyHandleL()
destructor
Definition: polygon.cpp:3455
bool DoCanConnectWith(a2dIterC &ic, a2dPin *pin, double margin, bool autocreate)
prepare an object for being connected to a given pin
Definition: polygon.cpp:2789
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
used to change a property on objects
Definition: drawing.h:2244
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: polygon.cpp:1575
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
clone it
Definition: polygon.cpp:3245
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
bool GetArcHandle()
is the handle on segment an arc modifier?
Definition: polygon.h:778
void Virtual_Point(a2dPoint2D &a_point, double distance) const
calculate point Perpendicula at distance from the line, through given point
Definition: liner.cpp:304
bool m_bin
Marker for walking over the segments.
Definition: polyver.h:238
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
a2dCanvasObjectList * m_childobjects
holds child objects
Definition: canobj.h:2562
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
clips all children to a polygon
Definition: polygon.h:617
void SetMode(int mode)
default used to modify rendering
Definition: canpin.h:307
polyline defined with list of points.
Definition: polygon.h:332
void Insert(unsigned int index, a2dLineSegmentPtr segin)
insert before segment with index given
Definition: polyver.cpp:1800
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
double GetContourWidth() const
get the Contour width of the shape
Definition: polygon.h:567
void SetPosXYMidSegment(a2dLineSegmentPtr seg, double x, double y, bool afterinversion=true)
modify middle point of arcsegment at index to x,y
Definition: polygon.cpp:784
std::list< T, std::allocator< T > >::iterator GetPreviousAround(typename std::list< T, std::allocator< T > >::iterator iter)
get the previous node ( –end() if no previous )
Definition: a2dlist.h:83
The point hits a member of the object (e.g. line begin/end object)
Definition: polyver.h:60
used to remove points from polygon objects
Definition: drawing.h:2070
void Walker(wxObject *parent, a2dWalkerIOHandler &handler)
This is used to recursively walk through an object tree.
Definition: gen.cpp:1473
void GetPosXYMidSegment(int index, double &x, double &y, bool transform=true) const
get middle point of arcsegment at index to x,y
Definition: polygon.cpp:667
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
virtual void DrawPolyPolygon(a2dListOfa2dVertexList polylist, wxPolygonFillMode fillStyle=wxODDEVEN_RULE)
draw a list of polygons ( contour clockwise becomes hole )
Definition: drawer2d.cpp:1881
a2dHit & GetHow()
in what manner the a2dCanvasObject was hit.
Definition: canglob.h:246
void SetSegments(a2dVertexList *points)
Set the list of points ( the old list is NOT DELETED !!! )
Definition: polygon.cpp:830
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
Normal straight line segment in a2dVpath.
Definition: polyver.h:878
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
snap to intersections in other objects
Definition: restrict.h:114
bool m_editable
object can be edited
Definition: candefs.h:295
virtual a2dVertexList * GetAsVertexList(bool &returnIsPolygon) const
convert to a polygon.
Definition: polygon.cpp:115
a2dCanvasObject * GetShowObject() const
return pointer of then currently shown object on the drawer.
Definition: drawer.h:680
void SetPosXYSegment(int index, double x, double y, bool afterinversion=true)
modify point at index to x,y
Definition: polygon.cpp:728
double wxRadToDeg(double rad)
conversion from radians to degrees
Definition: artglob.cpp:31
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
void SetSpecificFlags(bool setOrClear, a2dCanvasObjectFlagsMask which)
set all bit flags in object that or true in mask to true or false
Definition: canobj.cpp:2645
#define EVT_CANVASOBJECT_MOUSE_EVENT(func)
static event table macro for a2dCanvasObject mouse event
Definition: canglob.h:312
a2dSLine
Definition: canprim.h:987
void SetContourWidth(double width)
Definition: vpath.h:155
Definition: bbox.h:27
void CalculateLineParameters()
Calculate the parameters if invalid.
Definition: liner.cpp:355
void Clear()
Remove and delete all points in the polygon.
Definition: polygon.cpp:3490
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: canobj.cpp:5569
virtual bool DisConnectAt(a2dPin *pin, bool undo=false)
Do Disconnect from another a2dCanvasObject by pin pointer.
Definition: canobj.cpp:7134
general event sent from a2dHandle to its parent a2dCanvasObject
Definition: canglob.h:273
int Release(a2dCanvasObjectFlagsMask mask=a2dCanvasOFlags::ALL, const wxString &classname=wxT(""), const a2dPropertyId *id=NULL, const wxString &name=wxT(""), bool now=true)
release only objects with the given mask and classname and has property named propertyname and object...
Definition: objlist.cpp:306
void Add(a2dVpathSegment *seg)
add a segment
Definition: polyver.h:1240
Restriction engine for editing restrictions like snapping.
Definition: restrict.h:88
a2dLineSegment * FindPinSegment(a2dPin *pinToFind, double margin=a2dACCUR)
find the segment where the pin is on.
Definition: polygon.cpp:3085
bool m_childrenOnSameLayer
Definition: candefs.h:311
bool HasPins(bool realcheck=false)
are there a2dPin derived children
Definition: canobj.cpp:6414
a2dVertexList::iterator GetNextAround(a2dVertexList::iterator iter)
get the next segment as a polygon ( begin() is no next )
Definition: polyver.cpp:1728
virtual void DrawLine(double x1, double y1, double x2, double y2)
Draw line in world coordinates.
Definition: drawer2d.cpp:2167
a2dHit HitTestPolyline(const a2dPoint2D &ptest, double margin)
extensive hittesting on vertex list seen as polyline.
Definition: polyver.cpp:3251
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:862
a2dPin * AddPin(const wxString name, double x, double y, wxUint32 a2dpinFlags, a2dPinClass *pinClass, bool undo=false)
add a a2dPin as child
Definition: canobj.cpp:6474
void SetBegin(a2dCanvasObject *begin)
set object to draw as begin point
Definition: polygon.cpp:1832
bool IsConnected(bool needsupdate, a2dCanvasObject *toConnect=0)
Is the object connected ( Optinal to specific object ) ?
Definition: canobj.cpp:6550
a2dPin * FindBeginPin()
Get the begin pin from the childs.
Definition: polygon.cpp:3030
void RemovePins(bool NotConnected=false, bool onlyTemporary=false, bool now=false)
Remove all a2dPin children.
Definition: canobj.cpp:6504
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: polygon.cpp:3509
virtual a2dCanvasObjectList * GetAsPolygons(bool transform=true) const
convert contour to a polygons and holes to seperate polygons.
Definition: polygon.cpp:3519
static double GetRoundFactor()
Definition: artglob.h:124
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: polygon.cpp:3377
a2dHandle * GetCanvasHandle()
return the handle object hit
Definition: canglob.h:287
the property is temporary and never saved
Definition: id.h:163
Contains a2dDrawing Class to hold a drawing.
virtual void SetHandleToIndex(a2dPolyHandleL *handle, unsigned int index)
a handle in editing is updated to a segment at index given
Definition: polygon.cpp:840
wxUint32 a2dSnapToWhatMask
mask for a2dSnapToWhat flags
Definition: restrict.h:26
void WriteEndAttributes(bool close=false)
&quot;Closes&quot; the start tag after writing all attributes (writes the &quot;&gt;&quot; or &quot;/&gt;&quot; bracket).
Definition: genxmlpars.cpp:837
virtual a2dCanvasObjectList * GetSnapVpath(a2dSnapToWhatMask snapToWhat)
return a vectorpath indicating on which point/segments the object likes to be snapped.
Definition: polygon.cpp:148
editing is completely controlled by tools. No handles are added
Definition: canobj.h:140
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
virtual void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: polygon.cpp:2642
bool m_snap
snapping of editable object or when moving
Definition: candefs.h:280
double GetContourWidth() const
get the Contour width of the shape
Definition: polygon.h:240
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: canobj.cpp:1739
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
a2dPoint2D GetPosXY() const
get position of object
Definition: canobj.h:533
wxMouseEvent & GetMouseEvent()
return the original mouse event that was redirected to the a2dCanvasObject
Definition: canglob.h:243
a2dVertexList * ConvertToContour(double distance, a2dPATH_END_TYPE pathtype, bool asPolygon=false)
create a contour around polygon/polyline
Definition: polyver.cpp:2608
a2dStroke GetDrawerStroke() const
get the current stroke
Definition: drawer2d.h:548
void RemoveRedundantPoints(a2dCanvasObject *sendCommandsTo=NULL)
remove all points that are redundant
Definition: polygon.cpp:3685
double GetAttributeValueDouble(const wxString &attrib, double defaultv=0)
Returns the double value of an attribute.
Definition: genxmlpars.cpp:474
a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
In derived object this should be overriden to calculate the boundingbox of the object without its chi...
Definition: polygon.cpp:1523
virtual void ExtendAndPushClippingRegion(a2dVertexList *points, bool spline=false, wxPolygonFillMode fillStyle=wxODDEVEN_RULE, a2dBooleanClip clipoperation=a2dCLIP_AND)=0
push on stack the current clipping region and extend clipping region
bool IsDynamicPin() const
return true if this pin is a dynamic pin
Definition: canpin.h:418
a2dPinClass * GetPinClass() const
return the pin class of this pin
Definition: canpin.h:356
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
void Render(a2dIterC &ic, OVERLAP clipparent)
render by first setting clipping box and next start rendering children and itself.
Definition: polygon.cpp:3255
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: polygon.cpp:2607
const a2dAffineMatrix & GetInverseParentTransform() const
inverse of GetParentTransform()
Definition: canobj.cpp:723
a2dPin * HasPinNamed(const wxString pinName, bool NotConnected=false)
are there a2dPin derived children which matches the given pin name?
Definition: canobj.cpp:6436
double m_y2
y2 y of arc midpoint
Definition: polyver.h:473
double GetPosY() const
get y position from affine matrix
Definition: canobj.h:530
double GetWorldStrokeExtend()
Definition: canobj.h:3403
int IndexOf(a2dLineSegment *object) const
Find the index of a specific object.
Definition: polyver.cpp:1788
void ConvertIntoSplinedPolygon(double Aber)
Definition: polyver.cpp:2869
bool DoUpdate(UpdateMode mode, const a2dBoundingBox &childbox, const a2dBoundingBox &clipbox, const a2dBoundingBox &propbox)
Update derived Object specific things ( mainly boundingbox)
Definition: polygon.cpp:3717
virtual a2dLineSegment * Clone()
create exact copy
Definition: polyver.cpp:250
void SetPosXYSegment(a2dLineSegmentPtr seg, double x, double y, bool afterinversion=true)
modify point at index to x,y
Definition: polygon.cpp:4504
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
snap segments middle of other objects in a2dCanvasObject::RestrictToObject()
Definition: restrict.h:118
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: polygon.cpp:1700
double m_x
x endpoint of line
Definition: polyver.h:232
struct for how a single object on one layer was hit
Definition: polyver.h:38
polygon defined with list of points for outer contour plus a list of hole polygons ...
Definition: polygon.h:502
double m_x
(world coordinates) hit point x as in a2dDrawingPart or any other top level
Definition: canobj.h:293
a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
In derived object this should be overriden to calculate the boundingbox of the object without its chi...
Definition: polygon.cpp:3696
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
void Remove180DegPoints(a2dCanvasObject *sendCommandsTo=NULL, bool removeZeroFirst=true)
remove segments which are opposite direction overlapping.
Definition: polygon.cpp:2136
a2dLineSegment * AddPoint(double x, double y, a2dLineSegmentPtr seg=NULL, bool afterinversion=true)
add point/segment after a segment.
Definition: polygon.cpp:356
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
a2dCanvasObjectList * GetAsCanvasVpaths(bool transform=true) const
when implemented the object without its children, is converted to
Definition: polygon.cpp:1869
#define EVT_CANVASOBJECT_LEAVE_EVENT(func)
static event table macro for a2dCanvasObject mouse leave event
Definition: canglob.h:316
a2dBoundingBox GetMappedBbox(a2dIterC &ic, bool withExtend=true)
first translate boundingbox with cworld and recalculate at new position
Definition: canobj.cpp:3256
double m_y
y endpoint of line
Definition: polyver.h:235
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
double PointDistanceOrhto(const a2dPoint2D &p, a2dPoint2D *nearest) const
Calculate the orthogonal distance of a point from the line. Works even if l==0.
Definition: liner.cpp:707
void SetStroke(const wxColour &strokecolor, double width=0, a2dStrokeStyle style=a2dSTROKE_SOLID)
Set a stroke for the object which will be used instead of the layer stroke.
Definition: canobj.cpp:2924
Line calculations.
Definition: liner.h:36
wxString GetAttributeValue(const wxString &attrib, const wxString &defaultv=wxT(""))
Returns the value of an attribute.
Definition: genxmlpars.cpp:450
a2dRestrictionEngine * GetRestrictionEngine()
Get restriction engine (grid snapping)
Definition: canglob.cpp:934
double GetUnitsScale()
this is the number that defines the physical dimension in meters / inch/ etc.
Definition: drawing.h:676
std::list< T, std::allocator< T > >::iterator GetNextAround(typename std::list< T, std::allocator< T > >::iterator iter)
get the next node ( begin() if no next )
Definition: a2dlist.h:95
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canpin.h:723
bool GetRelease() const
get release flag
Definition: gen.h:1350
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
get a pointer to the command processor
Definition: drawing.cpp:375
double m_y1
y endpoint of line
Definition: polyver.h:922
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: polygon.cpp:1736
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: polygon.cpp:110
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: polygon.cpp:3358
double GetHitMarginWorld()
Get HitMargin in World units.
Definition: canobj.cpp:606
virtual bool AdjustAfterChange(bool final)
adjust the polygon after a point change
Definition: polygon.cpp:835
void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: polygon.cpp:1662
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
An object of this class will update a a2dIterC with the required information.
Definition: canobj.h:3123
void Require(const XMLeventType &type, wxString name)
Forces a special tag.
Definition: genxmlpars.cpp:390
if set, don&#39;t stop at the first hit, but test child/sibling objects anyway
Definition: canobj.h:97
void SetPointAdjustArcs(unsigned int n, double x, double y, bool polygon)
sets a point of a segment and adjusts arc it midpoints.
Definition: polyver.cpp:1879
wxString GetTagName()
Returns name of the current XML tag.
Definition: genxmlpars.cpp:565
a2dAffineMatrix m_ClipLworld
clipping matrix.
Definition: polygon.h:658
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
bool Scale(double scale)
Scale by scale (isotropic scaling i.e. the same in x and y):
Definition: afmatrix.cpp:270
bool Translate(double x, double y)
Translate by dx, dy:
Definition: afmatrix.cpp:420
a2dVertexList * GetAsVertexList(bool &returnIsPolygon) const
convert to a polygon.
Definition: polygon.cpp:3514
a2dBoundingBox DoGetUnTransformedBbox(a2dBboxFlags flags=a2dCANOBJ_BBOX_NON) const
In derived object this should be overriden to calculate the boundingbox of the object without its chi...
Definition: polygon.cpp:2215
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: polygon.cpp:3816
const a2dStroke * a2dTRANSPARENT_STROKE
global a2dStroke stock object for TRANSPARENT stroking
bool m_editingCopy
true if the object needs to be rendered in edit mode.
Definition: candefs.h:304
bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: polygon.cpp:3887
virtual bool EliminateMatrix()
reduce matrix to identity
Definition: canobj.cpp:6191
a2dFill GetDrawerFill() const
get the current fill
Definition: drawer2d.h:557
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
Does hit test on the object (exclusif child objects)
Definition: polygon.cpp:3860
virtual void PopClippingRegion()=0
pop a previously pushed clipping region
a2dPin * GetPin()
see SetPin()
Definition: polygon.h:789
a2dHit HitTestPolygon(const a2dPoint2D &ptest, double margin)
extensive hittesting on vertex list seen as polygon.
Definition: polyver.cpp:3050
a2dRect
Definition: canprim.h:440
base classes for tools and controller on top of the tools.
a2dCanvasObject * IsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
If the position (x,y) is within the object return this.
Definition: canobj.cpp:3415
void InsertSegment(unsigned int index, a2dLineSegmentPtr segin)
insert segment after index given
Definition: polygon.cpp:4450
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
void Contour(double distance, a2dPATH_END_TYPE pathtype)
create an offset contour at distance
Definition: polyver.cpp:4429
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: polygon.cpp:3331
all polygon and polyline a2dCanvasObject are here.
virtual bool WalkTask(wxObject *parent, wxObject *object, a2dWalkEvent event)
called from within a2dObject&#39;s and derived classes
Definition: gen.cpp:5265
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
float GetWidth() const
Definition: stylebase.cpp:6281
a2dArc centered at x,y
Definition: canprim.h:823
the a2dDrawingPart is a a2dView specially designed for displaying parts of a a2dDrawing. It uses a a2dDrawer2D to actually redraw things from the document, by giving that a2dDrawer2D as drawing context to the document, and telling the document to redraw a certain rectangular area. At that last is what this class is for. It optimizes the areas to be redrawn after object in the document were changed. To do that it combines redraw areas to a minimal set of redrawing areas. All the administration for this and the way things will be redrawn is from this view.
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: polygon.cpp:3748
double m_x1
x endpoint of line
Definition: polyver.h:919
void SetPosXyPoint(const a2dPoint2D &pos)
set position to x,y
Definition: canobj.h:547
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
void DoRender(a2dIterC &ic, OVERLAP clipparent)
render derived object
Definition: polygon.cpp:2352
A2DGENERALDLLEXP a2dWalkEvent a2dWalker_a2dDerivedCanvasObjectEnd
id for a2dWalkEvent issued from within a2dWalkerIOHandler
a2dCanvasGlobal * a2dCanvasGlobals
global a2dCanvasGlobal to have easy access to global settings
Definition: canglob.cpp:1234
virtual void DrawCircle(double x, double y, double radius)
Draw Circle in world coordinates.
Definition: drawer2d.cpp:2116
virtual void Save(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dObjectList *towrite)
write all needed to an XML type of file called the CVG format
Definition: gen.cpp:1343
a2dCanvasObject for a Vector Path
Definition: vpath.h:55
size_t GetNumberOfSegments()
get the number of points in the pointlist
Definition: polygon.h:229
a2dDrawingPart * GetDrawingPart() const
get current a2dDrawingPart
Definition: canobj.cpp:631
This template class is for property ids with a known data type.
Definition: id.h:477
double GetScale()
See GetScale()
Definition: genxmlpars.h:545
a2dBoundingBox m_bbox
boundingbox in world coordinates
Definition: canobj.h:2539
Vector Path.
Definition: polyver.h:1211
virtual void RemoveSegment(double &x, double &y, a2dLineSegmentPtr seg=NULL, bool transformed=true)
removes point at index
Definition: polygon.cpp:531
static const a2dCanvasObjectFlagsMask ALL
Definition: candefs.h:220
void RemoveRedundantPoints(a2dCanvasObject *sendCommandsTo=NULL)
remove all points that are redundant
Definition: polygon.cpp:417
void GetPosXYSegment(int index, double &x, double &y, bool transform=true) const
get point x and y at index
Definition: polygon.cpp:605
virtual void DrawLines(a2dVertexArray *points, bool spline=false)
Draw polyline in world coordinates using pointarray.
Definition: drawer2d.cpp:1931
double GetAbsX() const
get absolute X position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:959
void Append(a2dCanvasObject *obj)
append a a2dCanvasObject to the childobjects
Definition: canobj.cpp:6224
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
const a2dAffineMatrix & GetTransform() const
Get the accumulated transform up to and including m_lworld of the current object. ...
Definition: canobj.cpp:663
void PopCursor()
pop a cursor from the cursor stack, and set display cursor to back
Definition: drawer.cpp:1059
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
void SetEnd(a2dCanvasObject *end)
set object to draw as end point
Definition: polygon.cpp:1840
list of a2dObject&#39;s
Definition: gen.h:3157
bool DoIsHitWorld(a2dIterC &ic, a2dHitEvent &hitEvent)
return this object if one of the objects it references is hit
Definition: polygon.cpp:2655
double m_rely
(world coordinates) hit point y relative to the canvas object its parent object(s) ...
Definition: canobj.h:291
virtual bool Update(UpdateMode mode)
Update the state of the object according to its current position etc.
Definition: polygon.cpp:3272
void SetRestrictPoint(double xSnap, double ySnap)
sets the point for snapping to
Definition: restrict.h:337
double m_y
(world coordinates) hit point y as in a2dDrawingPart or any other top level
Definition: canobj.h:295
double DeviceToWorldXRel(double x) const
convert x relative from device to world coordinates
Definition: drawer2d.h:444
CloneOptions
options for cloning
Definition: gen.h:1200
const a2dAffineMatrix & GetUserToDeviceTransform() const
get matrix which transforms directly from user coordinates to device
Definition: drawer2d.h:503
a2dPoint2D GetMidPoint() const
get middle on arc segment between end and start
Definition: polyver.h:448
structure to give as parameter to member functions of a2dCanvasObject
Definition: canobj.h:252
virtual bool RestrictPoint(double &x, double &y, wxUint32 sourceRequired=snapToAll, bool ignoreEngine=false)
Restrict a single point of a line or polyline.
Definition: restrict.cpp:227
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: polygon.cpp:1848
const double wxPI
defines PI
Definition: artglob.cpp:28
wxInt64 GetUniqueSerializationId() const
return a unique id for this object
Definition: gen.cpp:1450
void SetFill(const a2dFill &fill)
Set a fill for the object which will be used instead of the layer fill.
Definition: canobj.cpp:2874
virtual void PushIdentityTransform()
push no transform, to draw directly in device coordinates
Definition: drawer2d.cpp:469
snap to pins in other objects
Definition: restrict.h:111
virtual void DoWalker(wxObject *parent, a2dWalkerIOHandler &handler)
iterate over this object and its children
Definition: canobj.cpp:5504
bool m_filled
use fill to fill if set
Definition: candefs.h:259
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: polygon.cpp:812
#define A2D_PROPID_D_F(type, propname, defaultval, flags)
to define a get set property more easily
Definition: id.h:714
const a2dFill * a2dTRANSPARENT_FILL
global a2dFill stock object for TRANSPARENT filling
static const a2dCanvasObjectFlagsMask PRERENDERASCHILD
Definition: candefs.h:198
general canvas module declarations and classes
void SetArcHandle(bool arcHandle)
set handle on segment as arc modifier
Definition: polygon.h:776
void WriteStartElement(const wxString &name, bool newLine=true)
Writes start tag which has no attributes.
Definition: genxmlpars.cpp:738
wxEditStyle
Definition: canobj.h:109
void OverRuleFixedStyle()
id style is FIXED, saves current style and sets style to a2dFILLED
Definition: drawer2d.cpp:697
polygon.cpp Source File -- Sun Oct 12 2014 17:04:23 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation