wxArt2D
wire.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/wire.cpp
2  \author Michael S�trop
3 
4  Copyright: 2003-2004 (c) Michael S�trop
5 
6  Licence: wxWidgets Licence
7 
8  RCS-ID: $Id: wire.cpp,v 1.71 2008/11/09 11:16:53 bionic-badger 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 "wx/canvas/wire.h"
24 
25 #include <float.h>
26 #include "wx/canvas/canobj.h"
27 #include "wx/canvas/drawer.h"
28 #include "wx/canvas/canvas.h"
29 #include "wx/canvas/tools.h"
30 #include "wx/canvas/canglob.h"
31 
32 //#include "wx/genart/prfl.h"
33 //#include "wx/genart/prfltmr.h"
34 //#include "wx/genart/prflcntmean.h"
35 //#include "wx/genart/prflenbl.h"
36 
37 //#define DUMP_FINAL
38 
39 //----------------------------------------------------------------------------
40 // a2dCommand_SplitAtPin
41 //----------------------------------------------------------------------------
42 
43 const a2dCommandId a2dCommand_SplitAtPin::Id( wxT( "SplitAtPin" ) );
44 
45 a2dCommand_SplitAtPin::a2dCommand_SplitAtPin( a2dCanvasObject* parent, a2dPin* splitPin, double hitMargin )
46 {
47  m_parent = parent;
48  m_splitPin = splitPin;
49  m_wire = wxStaticCast( m_splitPin->GetParent(), a2dWirePolylineL );
50  m_clone = NULL;
51  m_hitMargin = hitMargin;
52 }
53 
54 a2dCommand_SplitAtPin::~a2dCommand_SplitAtPin()
55 {
56 }
57 
59 {
60  m_splitPinClone = m_wire->SplitAtPin( m_parent, m_splitPin, NULL, NULL, m_hitMargin );
61  m_clone = wxStaticCast( m_splitPinClone->GetParent(), a2dWirePolylineL );
62 
63  if ( m_splitPinClone )
64  return true;
65  return false;
66 }
67 
69 {
70  a2dWirePolylineL* wire = wxStaticCast( m_splitPin->GetParent(), a2dWirePolylineL );
71  bool done = wire->JoinAtPin( m_parent, m_splitPin, m_splitPinClone );
72  wxASSERT( done );
73  return done;
74 }
75 
77 {
78  m_wire->SplitAtPin( m_parent, m_splitPin, m_splitPinClone, m_clone, m_hitMargin );
79  return true;
80 }
81 
82 //----------------------------------------------------------------------------
83 // a2dCommand_JoinAtPin
84 //----------------------------------------------------------------------------
85 
86 const a2dCommandId a2dCommand_JoinAtPin::Id( wxT( "JoinAtPin" ) );
87 
88 a2dCommand_JoinAtPin::a2dCommand_JoinAtPin( a2dCanvasObject* parent, a2dPin* joinPin, a2dPin* joinPin2 )
89 {
90  m_parent = parent;
91  m_joinPin = joinPin;
92  m_joinPin2 = joinPin2;
93  m_wire = wxStaticCast( m_joinPin->GetParent(), a2dWirePolylineL );
94  m_wirePin2 = wxStaticCast( m_joinPin2->GetParent(), a2dWirePolylineL );
95  m_secondRedirect = false;
96  m_inFront = false;
97 }
98 
99 a2dCommand_JoinAtPin::~a2dCommand_JoinAtPin()
100 {
101 }
102 
104 {
105  a2dPin* beginConnected = m_wirePin2->FindBeginPin();
106  a2dPin* endConnected = m_wirePin2->FindEndPin();
108 
109  bool done = m_wire->MergAtPin( m_parent, m_joinPin, m_joinPin2, m_inFront, m_secondRedirect );
110 
111  if ( m_secondRedirect )
112  {
113  if ( m_inFront )
114  m_renamedPin = endConnected;
115  else
116  m_renamedPin = beginConnected;
117  }
118 
119  wxASSERT( done );
120  return done;
121 }
122 
124 {
125  m_wire->SetSegments( m_oldwire->GetSegments() );
126  m_wirePin2->SetRelease( false );
127 
128  // remove all pins on the wire, in order to replace with the old ones.
129  a2dCanvasObjectList::iterator iterpins = m_wire->GetChildObjectList()->begin();
130  while( iterpins != m_wire->GetChildObjectList()->end() )
131  {
132  a2dCanvasObject* obj = *iterpins;
133  a2dPin* pin = wxDynamicCast( obj, a2dPin );
134  if ( pin && !pin->GetRelease() )
135  {
136  a2dPin* pin = wxDynamicCast( obj, a2dPin );
137  iterpins = m_wire->GetChildObjectList()->erase( iterpins );
138  }
139  else
140  iterpins++;
141  }
142 
143  //add pins and set old parent again.
144  iterpins = m_oldwire->GetChildObjectList()->begin();
145  while( iterpins != m_oldwire->GetChildObjectList()->end() )
146  {
147  a2dCanvasObject* obj = *iterpins;
148  a2dPin* pin = wxDynamicCast( obj, a2dPin );
149  if ( pin && !pin->GetRelease() )
150  {
151  pin->SetParent( m_wire );
152  m_wire->GetChildObjectList()->push_back( pin );
153  }
154  iterpins++;
155  }
156  iterpins = m_wirePin2->GetChildObjectList()->begin();
157  while( iterpins != m_wirePin2->GetChildObjectList()->end() )
158  {
159  a2dCanvasObject* obj = *iterpins;
160  a2dPin* pin = wxDynamicCast( obj, a2dPin );
161  if ( pin && !pin->GetRelease() )
162  {
163  pin->SetParent( m_wirePin2 );
164  }
165  iterpins++;
166  }
167 
168  m_parent->Append( m_wirePin2 );
169 
170  if ( m_secondRedirect && m_renamedPin )
171  {
172  if ( m_inFront )
173  m_renamedPin->SetName( wxT( "end" ) );
174  else
175  m_renamedPin->SetName( wxT( "begin" ) );
176  }
177 
178  //m_joinPin2->DuplicateConnectedPins( m_joinPin );
179  m_joinPin->ConnectTo( m_joinPin2 );
180 
181  return true;
182 }
183 
185 {
186  bool done = m_wire->MergAtPin( m_parent, m_joinPin, m_joinPin2, m_inFront, m_secondRedirect );
187  wxASSERT( done );
188  return true;
189 }
190 
191 //----------------------------------------------------------------------------
192 // a2dCommand_EliminateMatrix
193 //----------------------------------------------------------------------------
194 
195 const a2dCommandId a2dCommand_EliminateMatrix::Id( wxT( "EliminateMatrix" ) );
196 
197 a2dCommand_EliminateMatrix::a2dCommand_EliminateMatrix( a2dWirePolylineL* wire )
198 {
199  m_wire = wire;
200 }
201 
202 a2dCommand_EliminateMatrix::~a2dCommand_EliminateMatrix()
203 {
204 }
205 
207 {
208  m_matrix = m_wire->GetTransformMatrix();
209  if ( !m_matrix.IsIdentity() )
210  m_wire->EliminateMatrix();
211  return true;
212 }
213 
215 {
216  if ( !m_matrix.IsIdentity() )
217  {
218  a2dAffineMatrix invert = m_matrix;
219  invert.Invert();
220  m_wire->GetSegments()->Transform( invert );
221 
222  if ( m_wire->GetChildObjectList() != wxNullCanvasObjectList )
223  {
225  {
226  a2dCanvasObject* obj = *iter;
227  if ( obj )
228  obj->Transform( invert );
229  }
230  }
231  m_wire->SetTransformMatrix( m_matrix );
232  }
233  return true;
234 }
235 
237 {
238  return Do();
239 }
240 
241 //----------------------------------------------------------------------------
242 // a2dCommand_RemoveZeroWire
243 //----------------------------------------------------------------------------
244 
245 const a2dCommandId a2dCommand_RemoveZeroWire::Id( wxT( "RemoveZeroWire" ) );
246 
247 a2dCommand_RemoveZeroWire::a2dCommand_RemoveZeroWire( a2dCanvasObject* parent, a2dWirePolylineL* wire )
248 {
249  m_parent = parent;
250  m_joinPin = NULL;
251  m_joinPin2 = NULL;
252  m_wire = wire;
253 }
254 
255 a2dCommand_RemoveZeroWire::~a2dCommand_RemoveZeroWire()
256 {
257 }
258 
260 {
261  a2dPin* begin = m_wire->FindBeginPin();
262  a2dPin* end = m_wire->FindEndPin();
263 
264  wxASSERT_MSG( begin->GetConnectedPinsNr() == 1, "Can only be used with one connected pin" );
265  wxASSERT_MSG( end->GetConnectedPinsNr() == 1, "Can only be used with one connected pin" );
266 
267  m_joinPin = begin->IsConnectedTo();
268  m_joinPin2 = end->IsConnectedTo();
269 
270  m_joinPin->Disconnect( begin );
271  m_joinPin2->Disconnect( end );
272 
273  if ( m_joinPin != m_joinPin2 ) //like zero to same pin of other object.
274  m_joinPin->ConnectTo( m_joinPin2 );
275 
276  // remove the connected wire from parent.
277  a2dCanvasObjectList::iterator iterp = m_parent->GetChildObjectList()->begin();
278  while( iterp != m_parent->GetChildObjectList()->end() )
279  {
280  a2dCanvasObject* obj = *iterp;
281 
282  if ( obj && obj == m_wire )
283  {
284  m_wire->SetRelease( true ); //Used to detect this event
285  iterp = m_parent->GetChildObjectList()->erase( iterp );
286  }
287  else
288  iterp++;
289  }
290  return true;
291 }
292 
294 {
295  m_wire->SetRelease( false );
296 
297  m_parent->Append( m_wire );
298 
299  //m_joinPin2->DuplicateConnectedPins( m_joinPin );
300  a2dPin* begin = m_wire->FindBeginPin();
301  a2dPin* end = m_wire->FindEndPin();
302  if ( m_joinPin != m_joinPin2 ) //like zero to same pin of other object.
303  m_joinPin->Disconnect( m_joinPin2 );
304  m_joinPin->ConnectTo( begin );
305  m_joinPin2->ConnectTo( end );
306 
307  return true;
308 }
309 
311 {
312  return Do();
313 }
314 
315 IMPLEMENT_DYNAMIC_CLASS( a2dWirePolylineL, a2dPolylineL )
316 IMPLEMENT_DYNAMIC_CLASS( a2dWireEnd, a2dCanvasObject )
317 
318 //----------------------------------------------------------------------------
319 // a2dWirePolylineL
320 //----------------------------------------------------------------------------
321 
322 BEGIN_EVENT_TABLE( a2dWirePolylineL, a2dPolylineL )
323  EVT_CHAR( a2dWirePolylineL::OnChar )
324 END_EVENT_TABLE()
325 
326 a2dWirePolylineL::a2dWirePolylineL()
327 {
328  m_inverted = false;
329  m_objBegin = NULL;
330  m_wireBegin = NULL;
331  m_wireEnd = NULL;
332  m_objEnd = NULL;
333  m_wasVertical = false;
334  m_oneLine = false;
335  m_reroute = false;
336  m_rerouteAdd = false;
337  m_priority = 0;
338  m_flags.m_generatePins = true;
339 }
340 
341 a2dWirePolylineL::a2dWirePolylineL( a2dVertexList* points, bool spline )
342  : a2dPolylineL( points, spline )
343 {
344  m_inverted = false;
345  m_objBegin = NULL;
346  m_wireBegin = NULL;
347  m_wireEnd = NULL;
348  m_objEnd = NULL;
349  m_wasVertical = false;
350  m_oneLine = false;
351  m_reroute = false;
352  m_rerouteAdd = false;
353  m_priority = 0;
354  m_flags.m_generatePins = true;
355 }
356 
357 a2dWirePolylineL::a2dWirePolylineL( const a2dWirePolylineL& poly, CloneOptions options, a2dRefMap* refs )
358  : a2dPolylineL( poly, options, refs )
359 {
360  // wxLogDebug( "Cloing a2dWirePolylineL %p into %p", &poly, this );
361 
362  m_flags.m_draggable = poly.m_flags.m_draggable;
363  m_wasVertical = poly.m_wasVertical;
364  m_inverted = poly.m_inverted;
365  m_objBegin = poly.m_objBegin;
366  m_wireBegin = poly.m_wireBegin;
367  m_wireEnd = poly.m_wireEnd;
368  m_objEnd = poly.m_objEnd;
369  m_oneLine = poly.m_oneLine;
370  m_reroute = false;
371  m_rerouteAdd = false;
372  m_priority = 0;
373  m_flags.m_generatePins = poly.m_flags.m_generatePins;
374 }
375 
376 a2dWirePolylineL::~a2dWirePolylineL()
377 {
378 }
379 
381 {
382  return new a2dWirePolylineL( *this, options, refs );
383 }
384 
386  bool inverted,
387  a2dPinClass* objBegin,
388  a2dPinClass* objEnd
389 )
390 {
391  m_inverted = inverted;
392  m_objBegin = objBegin;
393  m_objEnd = objEnd;
394 }
395 
397 {
398  return true;
399 }
400 
402 {
403  return true;
404 }
405 
407 {
408  if ( m_lsegments->size() < 2 )
409  return;
410 
411  for( a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin(); iter != GetChildObjectList()->end(); ++iter )
412  {
413  a2dCanvasObject* obj = *iter;
414  a2dPin* pin = wxDynamicCast( obj, a2dPin );
415  if( !pin ) continue;
416 
417  double xOld = pin->GetPosX();
418  double yOld = pin->GetPosY();
419 
420  if( pin->GetName() == wxT( "begin" ) )
421  {
422  // regular begin pin
423  double xb, yb;
424  double xbp, ybp;
425  GetPosXYSegment( 0, xb, yb, false );
426  GetPosXYSegment( 1, xbp, ybp, false );
427  double angle = wxRadToDeg( atan2( yb-ybp, xb-xbp ) );
428  pin->SetRotation( angle );
429  pin->SetPosXY( xb, yb );
430  }
431  else if( pin->GetName() == wxT( "end" ) )
432  {
433  // regular end pin
434  double xe, ye;
435  double xep, yep;
436  GetPosXYSegment( -1, xe, ye, false );
437  GetPosXYSegment( m_lsegments->size()-2, xep, yep, false );
438  double angle = wxRadToDeg( atan2( ye-yep, xe-xep ) );
439  pin->SetRotation( angle );
440  pin->SetPosXY( xe, ye );
441  }
442  }
443  return;
444 }
445 
447 {
448  bool changed = false;
449  for( a2dCanvasObjectList::iterator iter = GetChildObjectList()->begin(); iter != GetChildObjectList()->end(); ++iter )
450  {
451  a2dCanvasObject* obj = *iter;
452  a2dPin* pin = wxDynamicCast( obj, a2dPin );
453  if( !pin ) continue;
454 
455  double xOld = pin->GetPosX();
456  double yOld = pin->GetPosY();
457 
458 // a2dPin *pinori = wxStaticCastNull( PROPID_Original->GetPropertyValue( pin ).Get(), a2dPin );
459 
460  if( pin->IsDynamicPin() )
461  {
462  // intermediate "dynamic" pin
463  if( MoveDynamicPinCloseTo( pin, pin->GetAbsXY(), final ) )
464  changed = true;
465  }
466  else if( pin->GetName() == wxT( "begin" ) )
467  {
468  // regular begin pin
469  double xNew, yNew;
470  GetPosXYSegment( 0, xNew, yNew, false );
471  if( xNew != xOld || yNew != yOld )
472  {
473  if ( m_root->GetCommandProcessor() && final )
474  m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
475  else
476  pin->SetPosXY( xNew, yNew );
477 
478  changed = true;
479  }
480  }
481  else if( pin->GetName() == wxT( "end" ) )
482  {
483  // regular end pin
484  double xNew, yNew;
485  GetPosXYSegment( -1, xNew, yNew, false );
486  if( xNew != xOld || yNew != yOld )
487  {
488  if ( m_root->GetCommandProcessor() && final )
489  m_root->GetCommandProcessor()->Submit( new a2dCommand_SetCanvasProperty( pin, PROPID_Position, a2dPoint2D( xNew, yNew ), -1, false ), final );
490  else
491  pin->SetPosXY( xNew, yNew );
492 
493  changed = true;
494  }
495  }
496  }
497 
498  return changed;
499 }
500 
501 a2dPin* a2dWirePolylineL::SplitAtPin( a2dCanvasObject* parent, a2dPin* splitPin, a2dPin* splitPinClone, a2dWirePolylineL* clone, double hitMargin )
502 {
503  wxASSERT_MSG( splitPin->GetParent() == this, "splitPin not part of wire" );
504 
505  if ( splitPin->GetName() == wxT( "end" ) || splitPin->GetName() == wxT( "begin" ) )
506  return NULL;
507 
508  //find on which segment pin is.
509  a2dHit hit = m_lsegments->HitTestPolyline( splitPin->GetPosXY(), hitMargin );
510  if ( hit.IsHit() )
511  {
512  a2dVertexList::iterator iter = m_lsegments->item( hit.m_index );
513  if ( !clone )
515  // we now have all segments in clone, but we want only from the splitpoint towards end
516  clone->m_lsegments->clear();
517  clone->m_childobjects->clear();
518  a2dVertexList::iterator iterc = clone->m_lsegments->begin();
519  clone->m_lsegments->splice( iterc, *m_lsegments, ++iter, m_lsegments->end() );
520  //extra segments at splitpoint
521 
522  // todo ( for the moment always add extra vertexes at split point, else in Undo not know if it happened or not,
523  // and a non added vertex would be removed.)
524  //if ( !hit.IsVertexHit() )
525  m_lsegments->push_back( new a2dLineSegment( splitPin->GetPosXY() ) );
526  // always add to other half.
527  clone->m_lsegments->push_front( new a2dLineSegment( splitPin->GetPosXY() ) );
528 
529  //decide where end is, to name the split pin in both parts.
530  //Move pins which are not on this wire, to the cloned (part2) wire, after the splitpoint.
531 
532  a2dPin* begin = FindBeginPin();
533  a2dPin* end = FindEndPin();
534  a2dPin* thisPinToPart2 = begin;
535 
536  bool beginAtStart = FindPinSegmentIndex( begin ) == 0;
537  //if begin and end pin are at the same location (head to tail case), the end is forced to wire part 2.
538  //Pins which are both on part1 and part2 (overlapping segments), stay on part1.
539  if ( beginAtStart )
540  thisPinToPart2 = end;
541 
542  bool foundSplitPin = false;
543  a2dCanvasObjectList::iterator iterpins = m_childobjects->begin();
544  while( iterpins != m_childobjects->end() )
545  {
546  a2dCanvasObject* obj = *iterpins;
547  if( !obj )
548  {
549  iterpins++;
550  continue;
551  }
552  a2dPin* pin = wxDynamicCast( obj, a2dPin );
553  if ( pin == splitPin )
554  foundSplitPin = true;
555  if( pin->IsTemporaryPin() )
556  {
557  iterpins = m_childobjects->erase( iterpins );
558  continue;
559  }
560  if ( pin != thisPinToPart2 )
561  {
562  a2dLineSegment* seg = FindPinSegment( pin );
563  if ( !seg )
564  {
565  clone->m_childobjects->push_back( pin );
566  pin->SetParent( clone );
567  iterpins = m_childobjects->erase( iterpins );
568  }
569  else
570  iterpins++;
571  }
572  else
573  {
574  clone->m_childobjects->push_back( pin );
575  pin->SetParent( clone );
576  iterpins = m_childobjects->erase( iterpins );
577  }
578  }
579 
580  if ( !foundSplitPin )
581  m_childobjects->push_back( splitPin );
582 
583  if ( !splitPinClone )
584  splitPinClone = wxStaticCast( splitPin->Clone( clone_members | clone_properties ), a2dPin );
585  splitPinClone->SetDynamicPin( false );
586  if ( beginAtStart )
587  {
588  splitPinClone->SetName( wxT( "begin" ) );
589  splitPin->SetName( wxT( "end" ) );
590  }
591  else
592  {
593  splitPin->SetName( wxT( "begin" ) );
594  splitPinClone->SetName( wxT( "end" ) );
595  }
596  splitPin->SetDynamicPin( false );
597  clone->Append( splitPinClone ); //sets parent to clone also
598  splitPinClone->DuplicateConnectedPins( splitPin );
599  splitPin->ConnectTo( splitPinClone );
600  parent->Append( clone );
601 
602  return splitPinClone;
603  }
604  return NULL;
605 }
606 
607 bool a2dWirePolylineL::JoinAtPin( a2dCanvasObject* parent, a2dPin* joinPin, a2dPin* joinPinOther )
608 {
609  wxASSERT_MSG( joinPin->GetParent() == this, "splitPin not part of wire" );
610 
611  if ( joinPin->GetName() != wxT( "end" ) && joinPin->GetName() != wxT( "begin" ) )
612  return false;
613 
614  if ( joinPinOther->GetName() != wxT( "end" ) && joinPinOther->GetName() != wxT( "begin" ) )
615  return false;
616 
617  a2dWirePolylineL* clone = wxStaticCast( joinPinOther->GetParent(), a2dWirePolylineL );
618 
619  a2dVertexList::iterator iter = m_lsegments->end();
620  m_lsegments->pop_back();
621  clone->m_lsegments->pop_front();
622 
623  m_lsegments->insert ( iter, clone->m_lsegments->begin(), clone->m_lsegments->end() );
624  //clone->m_lsegments->clear();
625 
626  joinPinOther->Disconnect( joinPin );
627  joinPinOther->RemoveDuplicateConnectedPins( joinPin );
628 
629  //move all pins to this wire
630  a2dCanvasObjectList::iterator iterpins = clone->m_childobjects->begin();
631  while( iterpins != clone->m_childobjects->end() )
632  {
633  a2dCanvasObject* obj = *iterpins;
634  if( !obj )
635  {
636  iterpins++;
637  continue;
638  }
639  a2dPin* pin = wxDynamicCast( obj, a2dPin );
640  if( pin->IsTemporaryPin() )
641  {
642  //iterpins = m_childobjects->erase( iterpins );
643  iterpins++;
644  continue;
645  }
646  if ( pin != joinPinOther )
647  m_childobjects->push_back( pin );
648  iterpins = clone->m_childobjects->erase( iterpins );
649  pin->SetParent( this );
650  }
651 
652  joinPin->SetName( wxT( "dynamic" ) );
653  joinPin->SetDynamicPin( true );
654 
655  a2dCanvasObjectList::iterator iterp = parent->GetChildObjectList()->begin();
656  while( iterp != parent->GetChildObjectList()->end() )
657  {
658  a2dCanvasObject* obj = *iterp;
659 
660  if ( obj && obj == clone )
661  iterp = parent->GetChildObjectList()->erase( iterp );
662  else
663  iterp++;
664  }
665  return true;
666 }
667 
668 bool a2dWirePolylineL::MergAtPin( a2dCanvasObject* parent, a2dPin* joinPin, a2dPin* joinPinOther, bool& inFront, bool& secondRedirect )
669 {
670  wxASSERT_MSG( joinPin->GetParent() == this, "splitPin not part of wire" );
671 
672  if ( joinPin->GetName() != wxT( "end" ) && joinPin->GetName() != wxT( "begin" ) )
673  return false;
674 
675  if ( joinPinOther->GetName() != wxT( "end" ) && joinPinOther->GetName() != wxT( "begin" ) )
676  return false;
677 
678  a2dWirePolylineL* wireConnected = wxStaticCast( joinPinOther->GetParent(), a2dWirePolylineL );
679 
680  a2dPin* begin = FindBeginPin();
681  a2dPin* end = FindEndPin();
682 
683  a2dPin* beginConnected = wireConnected->FindBeginPin();
684  a2dPin* endConnected = wireConnected->FindEndPin();
685 
686  inFront = false;
687  if ( begin == joinPin && joinPinOther == endConnected ) //same direction
688  {
689  inFront = true;
690  a2dVertexList::reverse_iterator iwireConnected = wireConnected->GetSegments()->rbegin();
691  iwireConnected++;
692  for( iwireConnected; iwireConnected != wireConnected->GetSegments()->rend(); ++iwireConnected )
693  m_lsegments->push_front( *iwireConnected );
694  }
695  else if ( end == joinPin && joinPinOther == endConnected ) //wrong direction, redirect
696  {
697  secondRedirect = true;
698  if ( beginConnected )
699  beginConnected->SetName( "end" );
700  a2dVertexList::reverse_iterator iwireConnected = wireConnected->GetSegments()->rbegin();
701  iwireConnected++;
702  for( iwireConnected; iwireConnected != wireConnected->GetSegments()->rend(); ++iwireConnected )
703  m_lsegments->push_back( *iwireConnected );
704  }
705  else if ( end == joinPin && joinPinOther == beginConnected ) //same direction
706  {
707  a2dVertexList::iterator iwireConnected = wireConnected->GetSegments()->begin();
708  iwireConnected++;
709  for( iwireConnected; iwireConnected != wireConnected->GetSegments()->end(); ++iwireConnected )
710  m_lsegments->push_back( *iwireConnected );
711  }
712  else if ( begin == joinPin && joinPinOther == beginConnected ) //wrong direction, redirect
713  {
714  inFront = true;
715  secondRedirect = true;
716  if ( endConnected )
717  endConnected->SetName( "begin" );
718  a2dVertexList::iterator iwireConnected = wireConnected->GetSegments()->begin();
719  iwireConnected++;
720  for( iwireConnected; iwireConnected != wireConnected->GetSegments()->end(); ++iwireConnected )
721  m_lsegments->push_front( *iwireConnected );
722  }
723 
724  joinPinOther->Disconnect( joinPin );
725  joinPinOther->RemoveDuplicateConnectedPins( joinPin );
726 
727  //remove join pin
728  a2dCanvasObjectList::iterator iterpins = m_childobjects->begin();
729  while( iterpins != m_childobjects->end() )
730  {
731  a2dCanvasObject* obj = *iterpins;
732  if( !obj || obj->GetRelease() )
733  {
734  iterpins++;
735  continue;
736  }
737  a2dPin* pin = wxDynamicCast( obj, a2dPin );
738  if ( pin == joinPin )
739  iterpins = m_childobjects->erase( iterpins );
740  else
741  iterpins++;
742  }
743 
744  //move all pins to this wire and remove but not joinPinOther
745  iterpins = wireConnected->m_childobjects->begin();
746  while( iterpins != wireConnected->m_childobjects->end() )
747  {
748  a2dCanvasObject* obj = *iterpins;
749  if( !obj || obj->GetRelease() )
750  {
751  iterpins++;
752  continue;
753  }
754  a2dPin* pin = wxDynamicCast( obj, a2dPin );
755  if( pin->IsTemporaryPin() )
756  {
757  //iterpins = m_childobjects->erase( iterpins );
758  iterpins++;
759  continue;
760  }
761  if ( pin != joinPinOther )
762  m_childobjects->push_back( pin );
763  iterpins++;
764  pin->SetParent( this );
765  }
766 
767  joinPin->CleanUpNonConnected();
768  joinPinOther->CleanUpNonConnected();
769 
770  // remove the connected wire from parent.
771  a2dCanvasObjectList::iterator iterp = parent->GetChildObjectList()->begin();
772  while( iterp != parent->GetChildObjectList()->end() )
773  {
774  a2dCanvasObject* obj = *iterp;
775 
776  if ( obj && obj == wireConnected )
777  {
778  wireConnected->SetRelease( true ); //Used to detect this event
779  iterp = parent->GetChildObjectList()->erase( iterp );
780  }
781  else
782  iterp++;
783  }
784  return true;
785 }
786 
788 {
789  a2dPin* begin = FindBeginPin();
790  a2dPin* end = FindEndPin();
791  if ( begin )
792  begin->SetName( "end" );
793  if ( end )
794  end->SetName( "begin" );
795  m_lsegments->reverse();
796 }
797 
798 void a2dWirePolylineL::OnChar( wxKeyEvent& event )
799 {
800  if ( m_flags.m_editingCopy )
801  {
802  switch( event.GetKeyCode() )
803  {
804  case WXK_DELETE:
805  {
806  a2dWirePolylineL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dWirePolylineL );
807  a2dPin* begin = original->FindBeginPin();
808  a2dPin* end = original->FindEndPin();
809 
810 
811  if ( m_lsegments->size() <= 2 )
812  {
813  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
814  break; // leaf at least one segment
815  }
816  //first delete selected segments ( nodes maybe selcted, and those nodes maybe removed because of this. (notice --m_childobjects->end())
817  for( a2dCanvasObjectList::iterator iter = ++m_childobjects->begin(); iter != --m_childobjects->end(); ++iter )
818  {
819  if ( m_lsegments->size() <= 2 )
820  {
821  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
822  break; // leaf at least one segment
823  }
824  a2dCanvasObject* obj = *iter;
825 
826  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
827 
828  if ( handle && !handle->GetRelease( ) )
829  {
830  a2dVertexList::iterator iterpoly = handle->GetNode();
831  a2dLineSegment* segment = *( iterpoly );
832  if ( segment->GetBin() ) //selected?
833  {
834  if ( handle->GetPin() == begin || handle->GetPin() == end )
835  {
836  wxLogWarning( _( "end or begin pins maybe not be deleted this way, select and remove whole wire instead" ) );
837  }
838  else
839  {
840  iter++;
841  a2dPolyHandleL* handle2 = wxDynamicCast( (*iter).Get(), a2dPolyHandleL );
842  iter--;
843  if ( handle2->GetPin() == begin || handle2->GetPin() == end )
844  {
845  wxLogWarning( _( "end or begin pins maybe not be deleted this way, select and remove whole wire instead" ) );
846  }
847  else
848  {
849  a2dLineSegment* segmentOrgNext = *( handle2->GetNodeOrg() );
850  a2dLineSegment* segmentOrg = *( handle->GetNodeOrg() );
851 
852  double xn,yn;
853  xn = (handle->GetPosX() + handle2->GetPosX())/2.0;
854  yn = (handle->GetPosY() + handle2->GetPosY())/2.0;
855  handle2->SetPosXY( xn, yn );
856  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
857  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( original, xn, yn, segmentOrgNext, false ) );
858  iterpoly = m_lsegments->erase( iterpoly );
859  (*iterpoly)->m_x = xn; (*iterpoly)->m_y = yn;
860  ReleaseChild( handle );
861  }
862  }
863  }
864  }
865  }
866 
867  //now delete selected handles (only those which were not released above).
868  for( a2dCanvasObjectList::iterator iter = m_childobjects->begin(); iter != m_childobjects->end(); ++iter )
869  {
870  a2dCanvasObject* obj = *iter;
871 
872  a2dPolyHandleL* handle = wxDynamicCast( obj, a2dPolyHandleL );
873 
874  if ( handle && !handle->GetRelease( ) && handle->GetSelected() )
875  {
876  if ( handle->GetPin() == begin || handle->GetPin() == end )
877  {
878  wxLogWarning( _( "end or begin pins maybe not be deleted this way, select and remove whole wire instead" ) );
879  }
880  else
881  {
882  a2dVertexList::iterator iterpoly = handle->GetNode();
883  a2dLineSegment* segment = *( iterpoly );
884  a2dVertexList::iterator iterorg = handle->GetNodeOrg();
885  a2dLineSegment* segmentOrg = *( iterorg );
886 
887  if ( m_lsegments->size() <= 2 )
888  {
889  wxLogWarning( _( "stopped removing segment or vertexes, object should keep at least one segment" ) );
890  break; // leaf at least one segment
891  }
892  else
893  {
894  m_root->GetCommandProcessor()->Submit( new a2dCommand_RemoveSegment( original, segmentOrg ) );
895  m_lsegments->erase( iterpoly );
896  ReleaseChild( handle );
897  }
898  }
899  }
900  }
901  original->AdjustAfterChange( true );
902  }
903  break;
904  default:
905  event.Skip();
906  }
907  }
908  else
909  event.Skip();
910 }
911 
912 bool a2dWirePolylineL::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
913 {
914  if ( m_flags.m_editable )
915  {
916  a2dWirePolylineL* original = wxDynamicCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dWirePolylineL );
917 
918  if ( editmode == 1 )
919  {
920  if( ! ( editstyle & wxEDITSTYLE_NOHANDLES ) )
921  {
922  a2dPin* begin = original->FindBeginPin();
923  a2dPin* end = original->FindEndPin();
924 
925  m_flags.m_visiblechilds = true;
927 
928  //add properties and handles as children in order to edit the object.
929  a2dVertexList::iterator iter = m_lsegments->begin();
930  a2dVertexList::iterator iterorg = original->GetSegments()->begin();
931  a2dLineSegment* seg;
932  while ( iter != GetSegments()->end() )
933  {
934  seg = ( *iter );
935 
936  /*
937  if ( ( iter != m_lsegments->begin() && iter != --m_lsegments->end() ) ||
938  ( iter == m_lsegments->begin() && !begin->IsConnectedTo() ) ||
939  ( iter == --m_lsegments->end() && !end->IsConnectedTo() )
940  )
941  */
942  {
943 
944  //not inclusive matrix so relative to polygon
945  a2dPolyHandleL* handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->GetSegments(), wxT( "__index__" ) );
946  Append( handle );
947  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
948  handle->SetLayer( m_layer );
949 
950  if ( seg->GetArc() )
951  {
952  // todo split in line segments ( maybe under certain conditions of matrix not?? ).
953  a2dArcSegment* cseg = ( a2dArcSegment* ) seg;
954 
955  handle = new a2dPolyHandleL( this, iter, iterorg, m_lsegments, original->GetSegments(), cseg->m_x2, cseg->m_y2, wxT( "__indexarc__" ) );
956  handle->SetArcHandle( true );
957  handle->SetLayer( m_layer );
958  Append( handle );
959  handle->SetSpecificFlags( true, a2dCanvasOFlags::BIN2 );
960  }
961 
962  if ( handle->GetPosXY() == begin->GetPosXY() )
963  handle->SetPin( begin );
964  if ( handle->GetPosXY() == end->GetPosXY() )
965  handle->SetPin( end );
966 
967  }
968  iter++;
969  iterorg++;
970  }
971 
972  m_childobjects->SetSpecificFlags( false, a2dCanvasOFlags::PRERENDERASCHILD, wxT( "a2dPolyHandleL" ) );
973  m_flags.m_editingCopy = true;
974 
975  //calculate bbox's elase mouse events may take place when first idle event is not yet
976  //processed to do this calculation.
978  //stil set it pending to do the redraw ( in place )
979  SetPending( true );
980  }
981  return true;
982  }
983  else
984  {
985  PROPID_Allowrotation->SetPropertyToObject( this, true );
986  PROPID_Allowskew->SetPropertyToObject( this, true );
987 
988  return a2dCanvasObject::DoStartEdit( editmode, editstyle );
989  }
990  }
991 
992  return false;
993 }
994 
995 #if wxART2D_USE_CVGIO
996 void a2dWirePolylineL::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut& out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
997 {
998  a2dPolylineL::DoSave( parent, out, xmlparts, towrite );
999  if ( xmlparts == a2dXmlSer_attrib )
1000  {
1001  out.WriteAttribute( wxT( "invert" ), m_inverted );
1002  out.WriteAttribute( wxT( "pcobjbegin" ), m_objBegin->GetName() );
1003  out.WriteAttribute( wxT( "pcwirebegin" ), m_wireBegin->GetName() );
1004  out.WriteAttribute( wxT( "pcwireend" ), m_wireEnd->GetName() );
1005  }
1006  else
1007  {
1008  }
1009 }
1010 void a2dWirePolylineL::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
1011 {
1012  a2dPolylineL::DoLoad( parent, parser, xmlparts );
1013  if ( xmlparts == a2dXmlSer_attrib )
1014  {
1015  m_inverted = parser.RequireAttributeValueBool( wxT( "invert" ) );
1016 
1017  wxString pinclass;
1018 
1019  pinclass = parser.RequireAttributeValue( wxT( "pcobjbegin" ) );
1021  if( !m_objBegin )
1022  {
1024  wxString reference_name = GetName();
1025  a2dGeneralGlobals->ReportErrorF( a2dError_NoPinClass, _( "a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)" ), reference_name.c_str(), pinclass.c_str() );
1026  }
1027 
1028  pinclass = parser.RequireAttributeValue( wxT( "pcwirebegin" ) );
1030  if( !m_wireBegin )
1031  {
1033  wxString reference_name = GetName();
1034  a2dGeneralGlobals->ReportErrorF( a2dError_NoPinClass, _( "a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)" ), reference_name.c_str(), pinclass.c_str() );
1035  }
1036 
1037  pinclass = parser.RequireAttributeValue( wxT( "pcwireend" ) );
1038  m_wireEnd = a2dPinClass::GetClassByName( pinclass );
1039  if( !m_wireEnd )
1040  {
1042  wxString reference_name = GetName();
1043  a2dGeneralGlobals->ReportErrorF( a2dError_NoPinClass, _( "a2dWirePolylineL with name %s \n Pin class %s not found (replaced with Standard)" ), reference_name.c_str(), pinclass.c_str() );
1044  }
1045  }
1046  else
1047  {
1048  }
1049 }
1050 #endif //wxART2D_USE_CVGIO
1051 
1052 void a2dWirePolylineL::SetEndPoint( int iEnd, int iNext, double x, double y, bool final )
1053 {
1054  double xPre, yPre;
1055  GetPosXYSegment( iEnd, xPre, yPre, true );
1056  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, x, y, iEnd, true ), final );
1057 
1058  if( GetNumberOfSegments() > 2 )
1059  {
1060  double xNext, yNext;
1061  GetPosXYSegment( iNext, xNext, yNext, true );
1062  bool isHor = fabs( yPre - yNext ) <= 1e-10 * wxMax( fabs( yPre ), fabs( yNext ) );
1063  bool isVert = fabs( xPre - xNext ) <= 1e-10 * wxMax( fabs( xPre ), fabs( xNext ) );
1064  // If the line segment adjacent to the end point is horizontal
1065  // move the adjacent point only vertically
1066  if( isHor && ! isVert || isHor && isVert && !m_wasVertical )
1067  {
1068  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, xNext, yNext + y - yPre, iNext, true ), final );
1069  m_wasVertical = false;
1070  }
1071  // If the line segment adjacent to the end point is vertical
1072  // move the adjacent point only horizontally
1073  if( isVert && ! isHor || isHor && isVert && m_wasVertical )
1074  {
1075  m_root->GetCommandProcessor()->Submit( new a2dCommand_MoveSegment( this, xNext + x - xPre, yNext, iNext, true ), final );
1076  m_wasVertical = true;
1077  }
1078  }
1079 }
1080 
1082 {
1083  return FindBeginPin()->IsDislocated() || FindEndPin()->IsDislocated();
1084 }
1085 
1086 bool a2dWirePolylineL::GeneratePinsPossibleConnections( a2dPinClass* pinClass, a2dConnectTask task, double x, double y, double margin )
1087 {
1088  wxASSERT_MSG( pinClass->GetConnectionGenerator()
1089  , wxT( "pinclass connection generator not set" ) );
1090 
1091  // m_wireBegin is used normally for creating new wires and pisn on that wire.
1092  // HERE it is used also for testing pin generation towards this line.
1093  // For task a2d_GeneratePinsForStartWire, a pin for a new wire is required, and
1094  // m_wireBegin is used to define/get the connection generator to use.
1095 
1096  if ( task == a2d_GeneratePinsForStartWire )
1097  //return m_wireBegin->GetConnectionGenerator()->GeneratePossibleConnections( this, m_wireBegin, task, x, y );
1098  //ask this wire, if it can connect to pinClass based on the m_wireBegin class
1099  return m_wireBegin->GetConnectionGenerator()->GeneratePossibleConnections( this, pinClass, task, x, y, margin );
1100  else if ( task == a2d_GeneratePinsForFinishWire )
1101  //return m_wireEnd->GetConnectionGenerator()->GeneratePossibleConnections( this, m_wireEnd, task, x, y );
1102  //ask this wire, if it can connect to pinClass based on the m_wireEnd class
1103  return m_wireEnd->GetConnectionGenerator()->GeneratePossibleConnections( this, pinClass, task, x, y, margin );
1104 
1105  return false;
1106 }
1107 
1108 bool a2dWirePolylineL::GeneratePins( a2dPinClass* toConnectTo, a2dConnectTask task, double x, double y, double margin )
1109 {
1110  a2dPinClass* toCreate = toConnectTo->GetPinClassForTask( task, this );
1111  if ( GetGeneratePins() && ( toCreate == m_wireBegin || toCreate == m_wireEnd ) )
1112  {
1113  m_flags.m_visiblechilds = true;
1114  bool end = false;
1115  bool begin = false;
1116  if ( !HasPinNamed( wxT( "begin" ) ) )
1117  {
1118  a2dVertexList::iterator iter = m_lsegments->begin();
1119  assert( m_lsegments->size() );
1120  AddPin( wxT( "begin" ), ( *iter )->m_x, ( *iter )->m_y, a2dPin::temporary, m_wireBegin );
1121  }
1122  else
1123  begin = true;
1124 
1125  if ( !HasPinNamed( wxT( "end" ) ) )
1126  {
1127  a2dVertexList::iterator iter = m_lsegments->end();
1128  assert( m_lsegments->size() );
1129  iter--;
1130  AddPin( wxT( "end" ), ( *iter )->m_x, ( *iter )->m_y, a2dPin::temporary, m_wireEnd );
1131  }
1132  else
1133  end = true;
1134 
1135  if ( /*begin && end &&*/ m_lsegments->size() > 0 )
1136  {
1137  // Find the rastered point on the line closest to the polygon line
1138  double xNear, yNear;
1139  if( FindNearPoint( &a2dIDENTITY_MATRIX, x, y, &xNear, &yNear ) )
1140  {
1141  a2dHit hit = m_lsegments->HitTestPolyline( a2dPoint2D( xNear, yNear ), a2dACCUR );
1142  if ( hit.IsHit() && ( hit.m_stroke2 == a2dHit::stroke2_edgevert || hit.m_stroke2 == a2dHit::stroke2_edgehor ) )
1143  {
1144  a2dRestrictionEngine* restrict = GetHabitat()->GetRestrictionEngine();
1145  if( restrict )
1146  {
1147  wxUint32 was = restrict->GetSnapSourceFeatures();
1149  //only modes which are usefull in dragging
1150  wxUint32 snapTo =
1151  a2dRestrictionEngine::snapToGridPos |
1153 
1154  restrict->RestrictPoint( xNear, yNear, snapTo, true );
1155  restrict->SetSnapSourceFeatures( was );
1156  }
1157  }
1158 
1159  a2dAffineMatrix inverse = m_lworld;
1160  inverse.Invert();
1161  double xNearLocal, yNearLocal;
1162  inverse.TransformPoint( xNear, yNear, xNearLocal, yNearLocal );
1163  double dx = fabs( xNear - x );
1164  double dy = fabs( yNear - y );
1165  if ( margin && ( dx > margin || dy > margin ) )
1166  return false;
1167 
1168  bool reuseTempPin = false;
1169  for( a2dCanvasObjectList::iterator iterpins = m_childobjects->begin(); iterpins != m_childobjects->end(); ++iterpins )
1170  {
1171  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1172  if( !pin || pin->GetRelease() ) continue;
1173  if ( pin->IsTemporaryPin() )
1174  {
1175  pin->SetPosXY( xNearLocal, yNearLocal );
1176  pin->SetRelease( false );
1177  reuseTempPin = true;
1178  //wxLogDebug(wxT("reuse x=%12.6lf, y=%12.6lf"), xNearLocal, yNearLocal );
1179  }
1180  }
1181 
1182  if ( !reuseTempPin )
1183  {
1184  //now we create a dynamic pin of the same class as a connected pin.
1185  a2dPin* pin = AddPin( wxT( "dynamic" ), xNearLocal, yNearLocal, a2dPin::temporary | a2dPin::dynamic, toCreate );
1187  pin->SetMouseInObject( true );
1188  //wxLogDebug(wxT("add x=%12.6lf, y=%12.6lf"), xNearLocal, yNearLocal );
1189  }
1190  }
1191  }
1192 
1193  wxASSERT( HasPins() );
1195 
1196  return true;
1197  }
1198  return false;
1199 }
1200 
1201 
1202 void a2dWirePolylineL::OptimizeRerouteWires( a2dCanvasObject* parent, bool removeZero, bool allowredirect )
1203 {
1205 
1206  //first remove all unconnected pins (not begin or end), since that looks better.
1207 
1208  if ( GetRelease() )
1209  return;
1210 
1211  a2dPin* begin = FindBeginPin();
1212  a2dPin* end = FindEndPin();
1213  for( a2dCanvasObjectList::iterator iterpins = GetChildObjectList()->begin(); iterpins != GetChildObjectList()->end(); ++iterpins )
1214  {
1215  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1216  if( !pin || pin->GetRelease( ) )
1217  continue;
1218 
1219  if ( begin != pin && end != pin )
1220  {
1221  if( !pin->IsConnectedTo() )
1222  {
1223  // cleanup unconnected pins when not at ends
1224  cmdh->Submit( new a2dCommand_ReleaseObject( this, pin ) );
1225  }
1226  continue;
1227  }
1228  }
1229 
1230  if ( removeZero )
1231  {
1232  if ( GetSegments()->Length() < a2dACCUR )
1233  {
1234  if ( begin->GetConnectedPinsNr() == 1 && end->GetConnectedPinsNr() == 1 )
1235  // merge pins into one, and remove this wire.
1236  cmdh->Submit( new a2dCommand_RemoveZeroWire( parent, this ) );
1237  }
1238  }
1239 
1240  if ( GetSegments()->Length() > a2dACCUR )
1241  {
1242  //For all connected objects, if a wire is only connected once, we can
1243  //possibly optimize it.
1244  // We need to iterate and delete nested (removing pins and wires etc.),
1245  // therefore we save the current situation to a list first.
1246  a2dCanvasObjectList savepins;
1247  for( a2dCanvasObjectList::iterator iterpins = GetChildObjectList()->begin(); iterpins != GetChildObjectList()->end(); ++iterpins )
1248  {
1249  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1250  if( !pin || pin->GetRelease( ) )
1251  continue;
1252 
1253  if ( pin->GetConnectedPinsNr() != 1 ) //just a single pin connection can be merged
1254  continue;
1255 
1256  savepins.push_back( pin );
1257  }
1258 
1259  // with the candiate connection, check the other connected wire
1260  for( a2dCanvasObjectList::iterator iterpins = savepins.begin(); iterpins != savepins.end(); ++iterpins )
1261  {
1262  a2dPin* pin = wxDynamicCast( iterpins->Get(), a2dPin );
1263  a2dPinList::const_iterator iterconp;
1264 
1265  //we have a one to one pin connection at end or begin pin towards another object.
1266  //If that is the same on a connected wire, we can merge the lines.
1267 
1268  a2dPinList savepinsother = pin->GetConnectedPins();
1269  for ( iterconp = savepinsother.begin( ) ; iterconp != savepinsother.end( ) ; iterconp++ )
1270  {
1271  a2dPin* otherpin = *iterconp;
1272 
1273  if( !otherpin || otherpin->GetRelease() )
1274  continue;
1275  if( !otherpin->IsConnectedTo() )
1276  continue;
1277  if ( otherpin->GetConnectedPinsNr() != 1 )
1278  continue;
1279 
1280  a2dCanvasObject* connectedobj = otherpin->GetParent();
1281  a2dWirePolylineL* wireConnected = wxDynamicCast( connectedobj, a2dWirePolylineL );
1282  if ( wireConnected &&
1283  ( wireConnected != this ) && // needs to be a different wire, in order to join.
1284  connectedobj->IsConnect() &&
1285  !connectedobj->GetBin() && !connectedobj->GetRelease() ) //selected wires are dragged and have bin flags set.
1286  {
1287  //If this wire can be combined with the connected wire, take over its pins and segments.
1288  //The two connected pins will be removed, and the connected wire also.
1289  SetPending( true ); //redraw the result/changed area.
1290 
1291  a2dPin* beginConnected = wireConnected->FindBeginPin();
1292  a2dPin* endConnected = wireConnected->FindEndPin();
1293 
1294  //do not join line of different style, unless they have zero lenght.
1295  if ( wireConnected->GetStroke() != GetStroke() && wireConnected->GetSegments()->Length() > a2dACCUR )
1296  continue;
1297 
1298  if ( begin == pin && otherpin == endConnected ) //same direction
1299  {
1300  cmdh->Submit( new a2dCommand_JoinAtPin( parent, pin, otherpin ) );
1301  }
1302  else if ( allowredirect && end == pin && otherpin == endConnected ) //wrong direction, redirect
1303  {
1304  cmdh->Submit( new a2dCommand_JoinAtPin( parent, pin, otherpin ) );
1305  }
1306  else if ( end == pin && otherpin == beginConnected ) //same direction
1307  {
1308  cmdh->Submit( new a2dCommand_JoinAtPin( parent, pin, otherpin ) );
1309  }
1310  else if ( allowredirect && begin == pin && otherpin == beginConnected ) //wrong direction, redirect
1311  {
1312  cmdh->Submit( new a2dCommand_JoinAtPin( parent, pin, otherpin ) );
1313  }
1314  }
1315  }
1316  }
1317  }
1318 
1319  EliminateMatrix();
1320 }
1321 
1322 //----------------------------------------------------------------------------
1323 // a2dWireEnd
1324 //----------------------------------------------------------------------------
1325 a2dWireEnd::a2dWireEnd( double x , double y )
1326  : a2dCanvasObject( x, y )
1327 {
1328 }
1329 
1330 a2dWireEnd::a2dWireEnd( const a2dWireEnd& obj, CloneOptions options, a2dRefMap* refs )
1331  : a2dCanvasObject( obj, options, refs )
1332 {
1333 }
1334 
1336 {
1337  return new a2dWireEnd( *this, options, refs );
1338 }
1339 
1340 //----------------------------------------------------------------------------
1341 // a2dCommand_VirtWire
1342 //----------------------------------------------------------------------------
1343 
1344 //! specialized command using the Assign method of Taco to transfer changes in editcopy to original.
1345 class A2DCANVASDLLEXP a2dCommand_VirtWire: public a2dCommand
1346 {
1347 public:
1348  static const a2dCommandId Id;
1349 
1350  a2dCommand_VirtWire() { m_target = NULL; }
1351  a2dCommand_VirtWire( a2dVirtWire* target, const wxString& VirtWireName );
1352  ~a2dCommand_VirtWire( void );
1353 
1354  bool Do();
1355  bool Undo();
1356 
1357  inline a2dCanvasCommandProcessor* GetCanvasCmp() { return wxStaticCast( m_cmp, a2dCanvasCommandProcessor ); }
1358 
1359 protected:
1360  a2dSmrtPtr<a2dVirtWire> m_target;
1361  wxString m_VirtWireName;
1362 };
1363 
1364 const a2dCommandId a2dCommand_VirtWire::Id( "a2dVirtWire" );
1365 
1366 a2dCommand_VirtWire::a2dCommand_VirtWire( a2dVirtWire* target, const wxString& VirtWireName )
1367  : a2dCommand( true, a2dCommand_VirtWire::Id )
1368 {
1369  m_target = target;
1370  m_VirtWireName = VirtWireName;
1371 }
1372 
1373 a2dCommand_VirtWire::~a2dCommand_VirtWire( void )
1374 {
1375 }
1376 
1378 {
1379  wxString VirtWireName = m_target->GetVirtWireName();
1380  m_target->SetVirtWireName( m_VirtWireName );
1381  m_target->SetPending( true );
1382  m_VirtWireName = VirtWireName;
1383  return true;
1384 }
1385 
1387 {
1388  Do();
1389  return true;
1390 }
1391 
1392 //----------------------------------------------------------------------------
1393 // a2dVirtWire
1394 //----------------------------------------------------------------------------
1395 
1396 wxIMPLEMENT_DYNAMIC_CLASS( a2dVirtWire, a2dText )
1397 
1398 a2dVirtWire::a2dVirtWire( a2dCanvasObject* parent, const wxString& VirtWireName, a2dPinClass* pinclass )
1399  : a2dText( "", 0.0, 0.0, *a2dDEFAULT_CANVASFONT, 0, false, wxMINX | wxMIDY ),
1400  m_VirtWireName( VirtWireName ),
1401  m_parent( parent )
1402 {
1403  m_flags.m_generatePins = false;
1404  m_text = " " + VirtWireName;
1405 
1406  a2dPin* pin = new a2dPin( this, wxT( "1" ), a2dPinClass::Standard, 0.0, 0.0 );
1407  Append( pin );
1408  pin->SetPinClass( pinclass );
1409 }
1410 
1411 a2dVirtWire::a2dVirtWire( const a2dVirtWire &other, CloneOptions options, a2dRefMap* refs )
1412  : a2dText( other, options, refs ),
1413  m_parent( other.m_parent )
1414 {
1415  m_VirtWireName = other.m_VirtWireName;
1416  m_text = " " + m_VirtWireName;
1417 }
1418 
1420 {
1421  return new a2dVirtWire( *this, options, refs );
1422 }
1423 
1424 bool a2dVirtWire::FindConnectedPins( a2dCanvasObjectList& result, a2dPin* pin, bool walkWires, a2dPinClass* searchPinClass, a2dCanvasObject* isConnectedTo )
1425 {
1426  bool hasConnectedPins = false;
1427  hasConnectedPins |= a2dText::FindConnectedPins( result, pin, walkWires, searchPinClass, isConnectedTo );
1428 
1429  SetBin( true );
1430  // find other a2dVirtWire object with the same name as this one, and go on on its pins (one for the moment).
1431  for( a2dCanvasObjectList::iterator iterp = m_parent->GetChildObjectList()->begin(); iterp != m_parent->GetChildObjectList()->end(); ++iterp )
1432  {
1433  a2dCanvasObject* obj = *iterp;
1434  a2dVirtWire* virtConnect = wxDynamicCast( obj, a2dVirtWire );
1435  if ( virtConnect && !virtConnect->GetBin() && virtConnect != this && !virtConnect->GetRelease() && virtConnect->m_VirtWireName == m_VirtWireName )
1436  {
1437  for( a2dCanvasObjectList::iterator iterpinssignal = virtConnect->m_childobjects->begin(); iterpinssignal != virtConnect->m_childobjects->end(); ++iterpinssignal )
1438  {
1439  a2dCanvasObject* obj = *iterpinssignal;
1440  if ( !obj )
1441  continue;
1442  a2dPin* pinOtherSignal = wxDynamicCast( obj, a2dPin );
1443  if ( pinOtherSignal && !pinOtherSignal->GetRelease( ) && !pinOtherSignal->GetBin() )
1444  {
1445  hasConnectedPins |= virtConnect->FindConnectedPins( result, NULL, walkWires, searchPinClass, isConnectedTo );
1446  }
1447  }
1448  }
1449  }
1450  return hasConnectedPins;
1451 }
1452 
1453 bool a2dVirtWire::DoStartEdit( wxUint16 editmode, wxEditStyle editstyle )
1454 {
1455  if ( m_flags.m_editable )
1456  {
1457  a2dVirtWire* original = wxStaticCast( PROPID_Original->GetPropertyValue( this ).Get(), a2dVirtWire );
1458  original->SetSelected( true );
1459 
1460  a2dVirtWireDlg dlg( NULL, this );
1461  int result = dlg.ShowModal();
1462  if (result == wxID_OK)
1463  {
1464  m_root->GetCommandProcessor()->Submit( new a2dCommand_VirtWire( original, dlg.GetVirtWire()->GetVirtWireName() ) );
1465  }
1466  // we trigger end editing directly, since all editing is finished after closing the dialog.
1467  original->SetEditing( false );
1468  return true;
1469  }
1470  return false;
1471 }
1472 
1473 void a2dVirtWire::DoSave( wxObject* parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts , a2dObjectList* towrite )
1474 {
1475  a2dText::DoSave( parent, out, xmlparts, towrite );
1476  if ( xmlparts == a2dXmlSer_attrib )
1477  {
1478  out.WriteAttribute( wxT( "virtName" ), m_VirtWireName );
1479  }
1480  else
1481  {
1482  }
1483 }
1484 
1485 void a2dVirtWire::DoLoad( wxObject* parent, a2dIOHandlerXmlSerIn& parser, a2dXmlSer_flag xmlparts )
1486 {
1487  a2dText::DoLoad( parent, parser, xmlparts );
1488  if ( xmlparts == a2dXmlSer_attrib )
1489  {
1490  m_VirtWireName = parser.RequireAttributeValue( wxT( "virtName" ) );
1491  }
1492  else
1493  {
1494  }
1495 }
1496 
1497 #define BBOX2XYWH(bbox) (bbox).GetMinX(), (bbox).GetMinY(), (bbox).GetWidth(), (bbox).GetHeight()
1498 
1499 void a2dVirtWire::DoRender( a2dIterC& ic, OVERLAP clipparent )
1500 {
1501  a2dDrawer2D* d(ic.GetDrawer2D());
1502 
1504 
1505 /*
1506  a2dVertexList* array = new a2dVertexList();
1507  array->push_back( new a2dLineSegment( 0.0, 0.0 ) );
1508  array->push_back( new a2dLineSegment( -1.5, 1.5 ) );
1509  array->push_back( new a2dLineSegment( -4.0, 1.5 ) );
1510  array->push_back( new a2dLineSegment( -4.0, -1.5 ) );
1511  array->push_back( new a2dLineSegment( -1.5, -1.5 ) );
1512 */
1513  a2dText::DoRender( ic, clipparent );
1514 }
1515 
1516 //----------------------------------------------------------------------------
1517 // a2dVirtDlg
1518 //----------------------------------------------------------------------------
1519 
1520 wxBEGIN_EVENT_TABLE( a2dVirtWireDlg, wxDialog )
1521 wxEND_EVENT_TABLE()
1522 
1523 a2dVirtWireDlg::a2dVirtWireDlg( wxWindow *parent, a2dVirtWire* virtWire )
1524 {
1525  wxDialog::Create( parent, -1, _("Wire-Name"), wxDefaultPosition, wxDefaultSize, wxCAPTION|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL );
1526  m_virtWire = virtWire;
1527  CreateControls();
1528  GetSizer()->SetSizeHints(this);
1529  Centre();
1530 }
1531 
1532 void a2dVirtWireDlg::CreateControls()
1533 {
1534  wxStaticText *st;
1535 
1536  bs = new wxBoxSizer(wxVERTICAL);
1537  SetSizer(bs);
1538 
1539  // Choose Signal Name
1540  bsN = new wxBoxSizer(wxHORIZONTAL);
1541  bs->Add(bsN, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
1542  st = new wxStaticText(this, wxID_ANY, _("Wire-Name") + ":");
1543  bsN->Add(st, 0, wxALIGN_CENTER_VERTICAL);
1544  bsN->AddSpacer(5);
1545 
1546  wxArrayString names;
1547  for( a2dCanvasObjectList::iterator iterp = m_virtWire->GetParent()->GetChildObjectList()->begin(); iterp != m_virtWire->GetParent()->GetChildObjectList()->end(); ++iterp )
1548  {
1549  a2dCanvasObject* obj = *iterp;
1550  a2dVirtWire* virtConnect = wxDynamicCast( obj, a2dVirtWire );
1551  if ( virtConnect && !virtConnect->GetRelease() )
1552  if (names.Index( virtConnect->GetVirtWireName() ) == wxNOT_FOUND)
1553  names.Add( virtConnect->GetVirtWireName() );
1554  }
1555  m_CBName = new wxComboBox( this, wxID_ANY, m_virtWire->GetVirtWireName(), wxDefaultPosition, wxSize(130, -1), names, wxCB_DROPDOWN );
1556  bsN->Add(m_CBName, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
1557 
1558  // Buttons
1559  wxStdDialogButtonSizer *sdbs = new wxStdDialogButtonSizer();
1560  bs->Add(sdbs, 0, wxGROW|wxALL, 5);
1561  wxButton *bOk = new wxButton( this, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
1562  sdbs->AddButton(bOk);
1563  wxButton *bCancel = new wxButton( this, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
1564  sdbs->AddButton(bCancel);
1565  wxButton *bHelp = new wxButton( this, wxID_HELP, _("&Help"), wxDefaultPosition, wxDefaultSize, 0 );
1566  sdbs->AddButton(bHelp);
1567  sdbs->Realize();
1568 
1569  m_CBName->Clear();
1570  m_CBName->Set(names);
1571  m_CBName->SetStringSelection( m_virtWire->GetVirtWireName() );
1572 
1573 }
1574 
1575 
1576 
1577 #define DIRECT 0
1578 #define INVERSE 1
1579 
1580 #define LEFT 0x00
1581 #define RIGHT 0x01
1582 #define BOTTOM 0x02
1583 #define TOP 0x03
1584 
1585 #define EQSIGN(x1, x2, x3, x4) ( ( x2 - x1 ) * ( x3 - x4 ) > 0 )
1586 
1587 #define CODE(x, y, w, h, px, py, c) { \
1588  c = 0x00; \
1589  if ( px < x ) c = 0x01; \
1590  else if ( px >= x + w ) c = 0x02; \
1591  if ( py < y ) c |= 0x04; \
1592  else if ( py >= y + h ) c |= 0x08; \
1593  }
1594 
1595 
1596 a2dSingleRoute::a2dSingleRoute( double offset, double smax )
1597 {
1598  m_offset = offset;//100;
1599  m_smax = smax;//400;
1600 }
1601 
1602 void a2dSingleRoute::ComputeCon ( a2dPin* outPad, a2dPin* inPad )
1603 {
1604  int diro = 0;
1605  double anglerad = wxDegToRad( outPad->GetAbsAngle() );
1606  if ( cos( anglerad ) > 0 )
1607  {
1608  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1609  diro = RIGHT;
1610  else if ( sin( anglerad ) > 0 )
1611  diro = TOP;
1612  else
1613  diro = BOTTOM;
1614  }
1615  else
1616  {
1617  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1618  diro = LEFT;
1619  else if ( sin( anglerad ) > 0 )
1620  diro = TOP;
1621  else
1622  diro = BOTTOM;
1623  }
1624  int diri = 0;
1625  anglerad = wxDegToRad( inPad->GetAbsAngle() );
1626  if ( cos( anglerad ) > 0 )
1627  {
1628  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1629  diri = RIGHT;
1630  else if ( sin( anglerad ) > 0 )
1631  diri = TOP;
1632  else
1633  diri = BOTTOM;
1634  }
1635  else
1636  {
1637  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1638  diri = LEFT;
1639  else if ( sin( anglerad ) > 0 )
1640  diri = TOP;
1641  else
1642  diri = BOTTOM;
1643  }
1644 
1645  Connect(outPad->GetAbsX(), outPad->GetAbsY(), diro, inPad->GetAbsX(), inPad->GetAbsY(), diri );
1646 
1647  a2dWirePolylineL* wire = NULL;
1648  a2dCanvasObject* startObj = outPad->GetParent();
1649  if ( startObj )
1650  {
1651  if ( wxDynamicCast( startObj, a2dWireEnd ) )
1652  startObj = a2dCanvasObject::PROPID_Original->GetPropertyValue( startObj );
1653  wire = wxDynamicCast( startObj, a2dWirePolylineL );
1654  if ( wire )
1655  Correct( outPad->GetAbsX(), outPad->GetAbsY(), 0, 0 );
1656  else
1657  {
1658  a2dBoundingBox bbox = startObj->GetCalculatedBoundingBox( 0 );
1659  Correct( bbox.GetMinX(), bbox.GetMinY(), bbox.GetWidth(), bbox.GetHeight() );
1660  }
1661  }
1662 
1663  a2dCanvasObject* endObj = inPad->GetParent();
1664  if ( endObj )
1665  {
1666  if ( wxDynamicCast( endObj, a2dWireEnd ) )
1667  endObj = a2dCanvasObject::PROPID_Original->GetPropertyValue( endObj );
1668  wire = wxDynamicCast( endObj, a2dWirePolylineL );
1669  if ( wire )
1670  Correct( inPad->GetAbsX(), inPad->GetAbsY(), 0, 0 );
1671  else
1672  {
1673  a2dBoundingBox bbox = endObj->GetCalculatedBoundingBox( 0 );
1674  Correct( bbox.GetMinX(), bbox.GetMinY(), bbox.GetWidth(), bbox.GetHeight() );
1675  }
1676  }
1677 
1678  return;
1679 }
1680 
1681 void a2dSingleRoute::ComputeConToWireVertex( a2dPin* outPad, double xw, double yw, double angle )
1682 {
1683  int diro = 0;
1684  double anglerad = wxDegToRad( outPad->GetAbsAngle() );
1685  if ( cos( anglerad ) > 0 )
1686  {
1687  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1688  diro = RIGHT;
1689  else if ( sin( anglerad ) > 0 )
1690  diro = TOP;
1691  else
1692  diro = BOTTOM;
1693  }
1694  else
1695  {
1696  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1697  diro = LEFT;
1698  else if ( sin( anglerad ) > 0 )
1699  diro = TOP;
1700  else
1701  diro = BOTTOM;
1702  }
1703  int diri = 0;
1704  anglerad = wxDegToRad( angle );
1705  if ( cos( anglerad ) > 0 )
1706  {
1707  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1708  diri = RIGHT;
1709  else if ( sin( anglerad ) > 0 )
1710  diri = TOP;
1711  else
1712  diri = BOTTOM;
1713  }
1714  else
1715  {
1716  if ( fabs( cos( anglerad ) ) > fabs( sin( anglerad )) )
1717  diri = LEFT;
1718  else if ( sin( anglerad ) > 0 )
1719  diri = TOP;
1720  else
1721  diri = BOTTOM;
1722  }
1723 
1724  Connect(outPad->GetAbsX(), outPad->GetAbsY(), diro, xw, yw, diri );
1725 
1726  a2dWirePolylineL* wire = NULL;
1727  a2dCanvasObject* startObj = outPad->GetParent();
1728  if ( startObj )
1729  {
1730  if ( wxDynamicCast( startObj, a2dWireEnd ) )
1731  startObj = a2dCanvasObject::PROPID_Original->GetPropertyValue( startObj );
1732  wire = wxDynamicCast( startObj, a2dWirePolylineL );
1733  if ( wire )
1734  Correct( outPad->GetAbsX(), outPad->GetAbsY(), 0, 0 );
1735  else
1736  {
1737  a2dBoundingBox bbox = startObj->GetCalculatedBoundingBox( 0 );
1738  Correct( bbox.GetMinX(), bbox.GetMinY(), bbox.GetWidth(), bbox.GetHeight() );
1739  }
1740  }
1741  return;
1742 }
1743 
1744 void a2dSingleRoute::Connect ( double xo, double yo, int diro, double xi, double yi, int diri )
1745 {
1746  static int directs[4][4] = {
1747  { TOP, BOTTOM, LEFT, RIGHT },
1748  { BOTTOM, TOP, RIGHT, LEFT },
1749  { RIGHT, LEFT, TOP, BOTTOM },
1750  { LEFT, RIGHT, BOTTOM, TOP }
1751  };
1752  int i;
1753  double txi, tyi;
1754 
1755  Transform(DIRECT, diro, xo, yo, xi, yi, &txi, &tyi);
1756  switch ( directs[diro][diri] ) { /* In pad direction */
1757  case LEFT:
1758  if ( tyi > 0 ) { /* T */
1759  if ( txi > 0 ) { /* 34 */
1760  Shape3P(txi, tyi);
1761  }
1762  else { /* 12 */
1763  Shape5PB(txi, tyi, -1);
1764  }
1765  }
1766  else { /* B */
1767  Shape5PB(txi, tyi, -1);
1768  }
1769  break;
1770  case RIGHT:
1771  if ( tyi > 0 ) { /* T */
1772  if ( txi > 0 ) { /* 34 */
1773  Shape5PB(txi, tyi, 1);
1774  }
1775  else { /* 12 */
1776  Shape3P(txi, tyi);
1777  }
1778  }
1779  else { /* B */
1780  Shape5PB(txi, tyi, 1);
1781  }
1782  break;
1783  case BOTTOM:
1784  if ( tyi > 0 ) { /* T */
1785  Shape4PD(txi, tyi);
1786  }
1787  else { /* B */
1788  Shape6P(txi, tyi, -1);
1789  }
1790  break;
1791  case TOP:
1792  if ( txi < - m_smax || txi > m_smax ) { /* 14 */
1793  Shape4PU(txi, tyi);
1794  }
1795  else { /* 23 */
1796  Shape6P(txi, tyi, 1);
1797  }
1798  break;
1799  }
1800  Optimize();
1801 
1802  for ( i = 0 ; i < m_pnr ; i++ )
1803  Transform(INVERSE, diro, xo, yo, m_p[i][0], m_p[i][1], &m_p[i][0], &m_p[i][1]);
1804 }
1805 
1806 
1807 /*****************************************************************************
1808 Translates & rotates a point according to the Out pad direction.
1809 
1810 Entry:
1811  mode - transformation mode (DIRECT or INVERSE)
1812  dout - Out pad direction
1813  xout - Out pad x coordinate
1814  yout - Out pad y coordinate
1815  x, y - point to be transformed
1816 Exit:
1817  tx, ty - transformed point
1818 *****************************************************************************/
1819 
1820 void a2dSingleRoute::Transform ( int mode, int dout, double xout, double yout, double x, double y, double* tx, double* ty )
1821 {
1822  double ox, oy;
1823 
1824  ox = x;
1825  oy = y;
1826  switch ( mode ) {
1827  case DIRECT:
1828  switch ( dout ) {
1829  case LEFT:
1830  *tx = oy - yout;
1831  *ty = xout - ox;
1832  break;
1833  case RIGHT:
1834  *tx = yout - oy;
1835  *ty = ox - xout;
1836  break;
1837  case BOTTOM:
1838  *tx = xout - ox;
1839  *ty = yout - oy;
1840  break;
1841  case TOP:
1842  *tx = ox - xout;
1843  *ty = oy - yout;
1844  break;
1845  }
1846  break;
1847  case INVERSE:
1848  switch ( dout ) {
1849  case LEFT:
1850  *tx = xout - oy;
1851  *ty = yout + ox;
1852  break;
1853  case RIGHT:
1854  *tx = xout + oy;
1855  *ty = yout - ox;
1856  break;
1857  case BOTTOM:
1858  *tx = xout - ox;
1859  *ty = yout - oy;
1860  break;
1861  case TOP:
1862  *tx = xout + ox;
1863  *ty = yout + oy;
1864  break;
1865  }
1866  break;
1867  }
1868 }
1869 
1870 
1871 /*****************************************************************************
1872 Corrects the connection path moving the overcrossing segments out of the
1873 crossed object.
1874 
1875 Entry:
1876  x, y - object lower left corner
1877  w, h - object width & height
1878  np - number of connection point
1879  p - original path points list
1880 Exit:
1881  p - eventually corrected path points list
1882 *****************************************************************************/
1883 
1884 void a2dSingleRoute::Correct ( double x, double y, double w, double h )
1885 {
1886  int i, j, c;
1887  double op[2], od[2];
1888 /*
1889  double m_po[8][2];
1890  for ( i = 0 ; i < m_pnr ; i++ )
1891  {
1892  m_po[m_pnr-i-1][0] = m_p[i][0];
1893  m_po[m_pnr-i-1][1] = m_p[i][1];
1894  }
1895  for ( i = 0 ; i < m_pnr ; i++ )
1896  {
1897  m_p[i][0] = m_po[i][0];
1898  m_p[i][1] = m_po[i][1];
1899  }
1900 */
1901  op[0] = x;
1902  op[1] = y;
1903  od[0] = w;
1904  od[1] = h;
1905  for ( j = 1, i = 2 ; i < m_pnr - 1 ; i++, j++ )
1906  {
1907  if ( Overcross(x, y, w, h, m_p[j][0], m_p[j][1], m_p[i][0], m_p[i][1]) )
1908  {
1909  c = ( m_p[j][0] == m_p[i][0] ) ? 0 : 1; //horizontal or vertical
1910  /*
1911  ----- Sn
1912  | Same direction
1913  Sp----|
1914 
1915  ----- Sn
1916  |
1917  | Different direction
1918  ----- Sp
1919  */
1920  if ( EQSIGN(m_p[j-1][c], m_p[j][c], m_p[i][c], m_p[i+1][c]) )
1921  {
1922  if ( m_p[j][c] < m_p[j-1][c] )
1923  m_p[j][c] = m_p[i][c] = op[c] - m_offset + 2;
1924  else
1925  m_p[j][c] = m_p[i][c] = op[c] + od[c] - 1 + m_offset - 2;
1926  }
1927  else
1928  {
1929  if ( m_p[i][c] < m_p[i+1][c] )
1930  m_p[j][c] = m_p[i][c] = op[c] - m_offset + 2;
1931  else
1932  m_p[j][c] = m_p[i][c] = op[c] + od[c] - 1 + m_offset - 2;
1933  }
1934  }
1935  }
1936 /*
1937  for ( i = 0 ; i < m_pnr ; i++ )
1938  {
1939  m_po[m_pnr-i-1][0] = m_p[i][0];
1940  m_po[m_pnr-i-1][1] = m_p[i][1];
1941  }
1942  for ( i = 0 ; i < m_pnr ; i++ )
1943  {
1944  m_p[i][0] = m_po[i][0];
1945  m_p[i][1] = m_po[i][1];
1946  }
1947 */
1948 }
1949 
1950 
1951 /*****************************************************************************
1952 Implementation of line-rectangle intersection test as the first test in
1953 Cohen-Sutherland clipping algorithm.
1954 
1955 Entry:
1956  x, y - rectangle lower left corner
1957  w, h - rectangle width & height
1958  x1, y1 - line start point
1959  x2, y2 - line end point
1960 Return:
1961  TRUE if the line overcrosses the rectangle, FALSE otherwise
1962 *****************************************************************************/
1963 
1964 int a2dSingleRoute::Overcross ( double x, double y, double w, double h, double x1, double y1, double x2, double y2 )
1965 {
1966  int c1, c2;
1967 
1968  CODE(x, y, w, h, x1, y1, c1);
1969  CODE(x, y, w, h, x2, y2, c2);
1970  return(! ( c1 & c2));
1971 }
1972 
1973 
1974 /*****************************************************************************
1975 Shape functions.
1976 
1977 Entry:
1978  xi, yi - In pad coordinate
1979  [sign] - sign flag
1980 Exit:
1981  xy - the computed path points list
1982 *****************************************************************************/
1983 
1984 void a2dSingleRoute::Shape3P ( double xi, double yi )
1985 {
1986  m_p[0][0] = 0;
1987  m_p[0][1] = 0;
1988  m_p[1][0] = 0;
1989  m_p[1][1] = yi;
1990  m_p[2][0] = xi;
1991  m_p[2][1] = yi;
1992  m_pnr = 3;
1993 }
1994 
1995 
1996 void a2dSingleRoute::Shape4PD ( double xi, double yi )
1997 {
1998  m_p[0][0] = 0;
1999  m_p[0][1] = 0;
2000  if ( m_offset )
2001  {
2002  m_p[1][0] = 0;
2003  m_p[1][1] = m_offset;
2004  m_p[2][0] = xi;
2005  m_p[2][1] = m_p[1][1];
2006  m_p[3][0] = xi;
2007  m_p[3][1] = yi;
2008  m_pnr = 4;
2009  }
2010  else
2011  {
2012  m_p[1][0] = xi;
2013  m_p[1][1] = 0;
2014  m_p[2][0] = xi;
2015  m_p[2][1] = yi;
2016  m_pnr = 3;
2017  }
2018 }
2019 
2020 
2021 void a2dSingleRoute::Shape4PU ( double xi, double yi )
2022 {
2023  m_p[0][0] = 0;
2024  m_p[0][1] = 0;
2025  if ( m_offset )
2026  {
2027  m_p[1][0] = 0;
2028  m_p[1][1] = ( ( yi <= 0 ) ? 0 : yi ) + m_offset;
2029  m_p[2][0] = xi;
2030  m_p[2][1] = m_p[1][1];
2031  m_p[3][0] = xi;
2032  m_p[3][1] = yi;
2033  m_pnr = 4;
2034  }
2035  else
2036  {
2037  m_p[1][0] = 0;
2038  m_p[1][1] = ( yi <= 0 ) ? 0 : yi;
2039  m_p[2][0] = xi;
2040  m_p[2][1] = m_p[1][1];
2041  m_p[3][0] = xi;
2042  m_p[3][1] = yi;
2043  m_pnr = 4;
2044  }
2045 }
2046 
2047 
2048 void a2dSingleRoute::Shape5PB ( double xi, double yi, int sign )
2049 {
2050  m_p[0][0] = 0;
2051  m_p[0][1] = 0;
2052  if ( m_offset )
2053  {
2054  m_p[1][0] = 0;
2055  m_p[1][1] = m_offset;
2056  if ( sign * xi < - m_smax )
2057  m_p[2][0] = xi + sign * m_offset;
2058  else
2059  m_p[2][0] = ( ( sign * xi < 0 ) ? 0 : xi ) + sign * m_offset;
2060  m_p[2][1] = m_p[1][1];
2061  m_p[3][0] = m_p[2][0];
2062  m_p[3][1] = yi;
2063  m_p[4][0] = xi;
2064  m_p[4][1] = yi;
2065  m_pnr = 5;
2066  }
2067  else
2068  {
2069  if ( sign * xi < - m_smax )
2070  m_p[1][0] = xi;
2071  else
2072  m_p[1][0] = ( ( sign * xi < 0 ) ? 0 : xi );
2073  m_p[1][1] = m_p[0][1];
2074  m_p[2][0] = m_p[1][0];
2075  m_p[2][1] = yi;
2076  m_p[3][0] = xi;
2077  m_p[3][1] = yi;
2078  m_pnr = 4;
2079  }
2080 }
2081 
2082 
2083 void a2dSingleRoute::Shape5PT ( double xi, double yi, int sign )
2084 {
2085  m_p[0][0] = 0;
2086  m_p[0][1] = 0;
2087  if ( m_offset )
2088  {
2089  m_p[1][0] = 0;
2090  m_p[1][1] = m_offset;
2091  m_p[2][0] = xi + sign * m_offset;
2092  m_p[2][1] = m_p[1][1];
2093  m_p[3][0] = m_p[2][0];
2094  m_p[3][1] = yi;
2095  m_p[4][0] = xi;
2096  m_p[4][1] = yi;
2097  m_pnr = 5;
2098  }
2099  else
2100  {
2101  m_p[1][0] = xi;
2102  m_p[1][1] = 0;
2103  m_p[2][0] = xi;
2104  m_p[2][1] = yi;
2105  m_pnr = 3;
2106  }
2107 }
2108 
2109 
2110 void a2dSingleRoute::Shape6P ( double xi, double yi, int sign )
2111 {
2112  double xm;
2113 
2114  xm = xi / 2;
2115  m_p[0][0] = 0;
2116  m_p[0][1] = 0;
2117  if ( m_offset )
2118  {
2119  m_p[1][0] = 0;
2120  m_p[1][1] = m_offset;
2121  if ( yi < 0 )
2122  {
2123  if ( xi > 0 )
2124  m_p[2][0] = ( xm > m_smax ) ? xm : m_smax;
2125  else
2126  m_p[2][0] = ( xm < -m_smax ) ? xm : - m_smax;
2127  }
2128  else
2129  {
2130  if ( xi > 0 )
2131  m_p[2][0] = ( xm > m_smax ) ? xm : - m_smax;
2132  else
2133  m_p[2][0] = ( xm < -m_smax ) ? xm : m_smax;
2134  }
2135  m_p[2][1] = m_p[1][1];
2136  m_p[3][0] = m_p[2][0];
2137  m_p[3][1] = yi + sign * m_offset;
2138  m_p[4][0] = xi;
2139  m_p[4][1] = m_p[3][1];
2140  m_p[5][0] = xi;
2141  m_p[5][1] = yi;
2142  m_pnr = 6;
2143  }
2144  else
2145  {
2146  if ( yi < 0 )
2147  {
2148  if ( xi > 0 )
2149  m_p[1][0] = ( xm > m_smax ) ? xm : m_smax;
2150  else
2151  m_p[1][0] = ( xm < -m_smax ) ? xm : - m_smax;
2152  }
2153  else
2154  {
2155  if ( xi > 0 )
2156  m_p[1][0] = ( xm > m_smax ) ? xm : - m_smax;
2157  else
2158  m_p[1][0] = ( xm < -m_smax ) ? xm : m_smax;
2159  }
2160  m_p[1][1] = 0;
2161  m_p[2][0] = m_p[1][0];
2162  m_p[2][1] = yi;
2163  m_p[3][0] = xi;
2164  m_p[3][1] = yi;
2165  m_pnr = 4;
2166  }
2167 }
2168 
2169 
2170 void a2dSingleRoute::Optimize ()
2171 {
2172  int i,j;
2173 /*
2174  double m_po[8][2];
2175  j = 0;
2176 
2177  m_po[0][0] = m_p[0][0];
2178  m_po[0][1] = m_p[0][1];
2179  for ( i = 1 ; i < m_pnr ; i++ )
2180  {
2181  if ( m_p[i][0] == m_p[j][0] && m_p[i][1] == m_p[j][1] )
2182  {
2183  }
2184  else
2185  {
2186  j++;
2187  m_po[j][0] = m_p[i][0];
2188  m_po[j][1] = m_p[i][1];
2189  }
2190  }
2191 
2192  m_pnr = j+1;
2193  for ( i = 0 ; i < m_pnr ; i++ )
2194  {
2195  m_p[i][0] = m_po[i][0];
2196  m_p[i][1] = m_po[i][1];
2197  }
2198  return;
2199 */
2200 
2201  j = 0;
2202  for ( i = 1 ; i < m_pnr ; i++ )
2203  {
2204  if ( m_p[i][0] == m_p[j][0] && m_p[i][1] == m_p[j][1] )
2205  continue;
2206  j++;
2207  if ( j != i )
2208  {
2209  m_p[j][0] = m_p[i][0];
2210  m_p[j][1] = m_p[i][1];
2211  }
2212  }
2213  m_pnr = j+1;
2214 
2215  j = 0;
2216  if ( m_pnr > 3 )
2217  {
2218  for ( i = 1 ; i < m_pnr-1 ; i++ )
2219  {
2220  if ( m_p[i][0] == m_p[j][0] && m_p[i][0] == m_p[i+1][0] ||
2221  m_p[i][1] == m_p[j][1] && m_p[i][1] == m_p[i+1][1] )
2222  continue;
2223  j++;
2224  if ( j != i )
2225  {
2226  m_p[j][0] = m_p[i][0];
2227  m_p[j][1] = m_p[i][1];
2228  }
2229  }
2230  }
2231  m_pnr = j+2;
2232 }
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
used to move points in polygon objects
Definition: drawing.h:1997
double GetHeight() const
returns height of the boundingbox
Definition: bbox.cpp:334
virtual bool Undo()=0
Override this to undo a command.
a2dPin * IsDislocated() const
Definition: canpin.cpp:1089
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
specialized command using the Assign method of Taco to transfer changes in editcopy to original...
Definition: wire.cpp:1345
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
Temporary object used in editing connected objects.
Definition: wire.h:202
#define wxDynamicCast(obj, className)
Define wxDynamicCast so that it will give a compiler error for unrelated types.
Definition: gen.h:75
unsigned int m_index
For edge/vertex hits the index of the edge / vertex.
Definition: polyver.h:89
bool GetGeneratePins() const
get the GeneratePins flag
Definition: canobj.h:2289
void Connect(double xo, double yo, int diro, double xi, double yi, int diri)
Definition: wire.cpp:1744
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 SetRotation(double rotation)
Sets a rotation of this object.
Definition: canobj.cpp:2609
virtual wxString GetName() const
Returns the name of this object, if no name is given the internal id will be returned.
Definition: gen.cpp:1310
#define a2dACCUR
accuracy used to have some limit to calculation like hittesting
Definition: artglob.h:41
a2dPinClass * m_objEnd
The pin class in the pin of the object at the end of the wire.
Definition: wire.h:172
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
bool RequireAttributeValueBool(const wxString &attrib)
Forces an attribute and returns its boolean value.
Definition: genxmlpars.cpp:551
generate pins, given Connect/wire pinclass
Definition: connectgen.h:49
class to map references to objects stored in XML, in order to make the connection later on...
Definition: gen.h:3462
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
virtual bool Do()=0
Override this to perform a command.
static const long sm_PinCanConnectToPinClass
Pin can connect to supplied a2dPinClass.
Definition: canpin.h:505
static const a2dCanvasObjectFlagsMask BIN2
Definition: candefs.h:193
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: wire.cpp:912
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
Ref Counted base object.
Definition: gen.h:1045
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: wire.cpp:1010
void SetTransformMatrix(const a2dAffineMatrix &mat=a2dIDENTITY_MATRIX)
Returns the matrix used to position the object.
Definition: canobj.h:509
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: polygon.cpp:2570
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load object specific CVG data.
Definition: cantext.cpp:536
double wxDegToRad(double deg)
conversion from degrees to radians
Definition: artglob.cpp:30
a2dObject * Clone(CloneOptions options, a2dRefMap *refs=NULL) const
create an exact copy of this property
Definition: gen.cpp:1199
bool Do()
Override this to perform a command.
Definition: wire.cpp:1377
generate pins, given Connect/wire pinclass
Definition: connectgen.h:48
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
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
write object specific CVGL data
Definition: wire.cpp:996
bool MergAtPin(a2dCanvasObject *parent, a2dPin *joinPin, a2dPin *joinPinOther, bool &inFront, bool &secondRedirect)
join two wires at joinPin and joinPinOther will be removed.
Definition: wire.cpp:668
bool IsIdentity(void) const
Is the matrix the identity matrix?
Definition: afmatrix.h:147
a2dBoundingBox GetCalculatedBoundingBox(int nChildLevels)
Like GetBbox, but it always calculcates the bounding box from scratch.
Definition: canobj.cpp:5072
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: wire.cpp:1335
Input and output handler for the XmlSer format.
Definition: genxmlpars.h:819
double m_x2
x2 x of arc midpoint
Definition: polyver.h:471
void SetSnapSourceFeature(a2dSnapToWhat snapSourceFeature, bool value=true)
set one of the snapping features for the source to true or false, leaf others as is ...
Definition: restrict.h:218
void OptimizeRerouteWires(a2dCanvasObject *parent, bool removeZero=true, bool allowredirect=true)
Definition: wire.cpp:1202
a command processor specially designed to work with a a2dCanvasDocument
Definition: drawing.h:1046
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
bool IsDislocated()
Check if the begin or end pin of the wire is dislocated.
Definition: wire.cpp:1081
bool m_wasVertical
This is used temporarily during editing and need not be saved.
Definition: wire.h:178
a2dPin * IsConnectedTo(a2dPin *pin=a2dAnyPin) const
Return the pin to which this pin is connected.
Definition: canpin.cpp:751
The base class for all drawable objects in a a2dCanvasDocument.
void Reverse()
make the direction of vertexes the oposite
Definition: wire.cpp:787
bool Do()
Override this to perform a command.
Definition: wire.cpp:103
Arc Segment in a2dVertexList.
Definition: polyver.h:371
wxUint16 m_layer
layer of object, default wxLAYER_DEFAULT
Definition: canobj.h:2556
a2dPoint2D GetAbsXY() const
get absolute position of the pin ( after applying the parent&#39;s matrix and its own matrix ) ...
Definition: canpin.cpp:952
a2dCanvasObject is the base class for Canvas Objects.
Definition: canobj.h:371
a2dAffineMatrix a2dIDENTITY_MATRIX
global a2dAffineMatrix to set/pass the identity matrix.
Definition: afmatrix.cpp:51
wxUint32 GetConnectedPinsNr() const
Get the number of connected pins.
Definition: canpin.cpp:738
bool Do()
Override this to perform a command.
Definition: wire.cpp:259
virtual bool GeneratePossibleConnections(a2dCanvasObject *object, a2dPinClass *pinClass, a2dConnectTask task, double x, double y, double margin) const
generate temporary pins to which objects can connect
virtual void SetParent(a2dCanvasObject *parent)
set parent object of the pin
Definition: canpin.cpp:932
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
a2dCanvas uses a2dCanvasView for displaying a view on a a2dCanvasDocument.
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
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Write object specific CVG data.
Definition: wire.cpp:1473
handle holds a pointer to a polygon/polyline segment
Definition: polygon.h:713
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
void SetBin(bool bin)
general flag use at will.
Definition: canobj.h:2259
double m_smax
object min half size
Definition: wire.h:406
void Transform(const a2dAffineMatrix &world)
transform all segments with given matrix
Definition: polyver.cpp:1928
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
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
bool m_generatePins
generate pins if true
Definition: candefs.h:268
bool MoveDynamicPinCloseTo(a2dPin *pin, const a2dPoint2D &point, bool final)
Move the given dynamic pin close to the given absolute point.
Definition: polygon.cpp:2993
void RemoveDuplicateConnectedPins(a2dPin *other)
pins connected to given other pin, will be removed on this pin.
Definition: canpin.cpp:895
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
If no other snap point was closer, force to grid, even if not within threshold.
Definition: restrict.h:141
bool Disconnect(a2dPin *pin=a2dAnyPin, bool forceErase=false)
Definition: canpin.cpp:789
bool m_draggable
can be dragged
Definition: candefs.h:253
a2dText is an abstract base class.
Definition: cantext.h:93
a2dCanvasObjectList * wxNullCanvasObjectList
define a NON a2dCanvasObjectList
Definition: objlist.cpp:53
used to change a property on objects
Definition: drawing.h:2244
void ConnectTo(a2dPin *connectto)
connect this pin to the given pin
Definition: canpin.cpp:918
virtual void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
Load object specific CVG data.
Definition: wire.cpp:1485
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
virtual void DrawRoundedRectangle(double x, double y, double width, double height, double radius, bool pixelsize=false)
Draw RoundedRectangle in world coordinates.
Definition: drawer2d.cpp:2048
virtual void DoRender(a2dIterC &ic, OVERLAP clipparent)
Render derived object.
Definition: wire.cpp:1499
bool Undo()
Override this to undo a command.
Definition: wire.cpp:68
a2dCanvasObjectList * m_childobjects
holds child objects
Definition: canobj.h:2562
virtual bool GeneratePinsPossibleConnections(a2dPinClass *pinClass, a2dConnectTask task, double x, double y, double margin=0)
generates pins on all possible locations where the wire can be connected.
Definition: wire.cpp:1086
void Transform(const a2dAffineMatrix &tworld)
transform the object using the given matrix
Definition: canobj.h:577
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: wire.cpp:380
void SetMode(int mode)
default used to modify rendering
Definition: canpin.h:307
polyline defined with list of points.
Definition: polygon.h:332
void SetPropertyToObject(a2dObject *obj, const basetype &value, SetFlags setflags=set_none) const
Set the property in obj to value.
Definition: id.inl:238
void AdjustBeginEndPinAngle()
adjust pin angles to the last segment at end and begin of wire.
Definition: wire.cpp:406
used to remove points from polygon objects
Definition: drawing.h:2070
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
bool JoinAtPin(a2dCanvasObject *parent, a2dPin *joinPin, a2dPin *joinPinOther)
Join two pins making one pin, and merge the this wire with the parent wire of the other pin...
Definition: wire.cpp:607
void ComputeCon(a2dPin *outPad, a2dPin *inPad)
Definition: wire.cpp:1602
void SetSegments(a2dVertexList *points)
Set the list of points ( the old list is NOT DELETED !!! )
Definition: polygon.cpp:830
bool Undo()
Override this to undo a command.
Definition: wire.cpp:214
a2dDrawer2D * GetDrawer2D() const
get current a2dDrawer2D
Definition: canobj.cpp:636
#define wxStaticCast(obj, className)
The wxWindows 2.4.2 wxStaticCast is buggy. It evaluates its argument twice.
Definition: gen.h:123
a2dVertexListPtr GetSegments()
Get the list of points ( this is not a copy! )
Definition: polygon.h:219
Drawing context abstraction.
Definition: drawer2d.h:177
bool m_editable
object can be edited
Definition: candefs.h:295
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
#define wxCLOSE_BOX
Definition: sttoolmes.h:37
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
virtual bool IsConnect() const
return true, if this object is used to connect other object&#39;s using rubberband like structures...
Definition: wire.cpp:396
void SetSnapSourceFeatures(wxUint32 snapSourceFeatures)
Definition: restrict.h:215
void SetEndPoint(int iEnd, int iNext, double x, double y, bool final)
Set position of an end point and possibly one adjacent point.
Definition: wire.cpp:1052
static a2dPinClass * GetClassByName(const wxString &name)
return the name of this pinclass.
Definition: canpin.cpp:511
A2DGENERALDLLEXP a2dSmrtPtr< a2dGeneralGlobal > a2dGeneralGlobals
a global pointer to get to global instance of important classes.
Definition: comevt.cpp:1148
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
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
bool GetBin() const
general flag use at will.
Definition: canobj.h:2262
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
double m_offset
first &amp; last segment min size
Definition: wire.h:404
a2dPin * FindBeginPin()
Get the begin pin from the childs.
Definition: polygon.cpp:3030
void ComputeConToWireVertex(a2dPin *outPad, double xw, double yw, double angle)
Definition: wire.cpp:1681
bool Undo()
Override this to undo a command.
Definition: wire.cpp:293
void CleanUpNonConnected()
Definition: canpin.cpp:726
wxString RequireAttributeValue(const wxString &attrib)
Forces an attribute and returns its string value.
Definition: genxmlpars.cpp:461
Each a2dCommand is given a command id at construction.
Definition: comevt.h:99
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 bool GeneratePins(a2dPinClass *toConnectTo, a2dConnectTask task, double x, double y, double margin=0)
Definition: wire.cpp:1108
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: canobj.cpp:1739
bool IsTemporaryPin() const
return true if this pin is a temporary pin
Definition: canpin.h:433
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
virtual a2dObject * DoClone(CloneOptions options, a2dRefMap *refs) const
Clone this object and return a pointer to the new object.
Definition: wire.cpp:1419
a2dPoint2D GetPosXY() const
get position of object
Definition: canobj.h:533
bool IsDynamicPin() const
return true if this pin is a dynamic pin
Definition: canpin.h:418
void DoLoad(wxObject *parent, a2dIOHandlerXmlSerIn &parser, a2dXmlSer_flag xmlparts)
load object specific CVG data
Definition: polygon.cpp:2607
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
a2dBoundingBox m_untransbbox
Untransformed bounding box.
Definition: cantext.h:396
while iterating a a2dCanvasDocument, this holds the context.
Definition: canobj.h:3212
const a2dError a2dError_NoPinClass
struct for how a single object on one layer was hit
Definition: polyver.h:38
All updates of these modes force an update (e.g. update non-pending valid bounding boxes) ...
Definition: canobj.h:1107
bool Do()
Override this to perform a command.
Definition: wire.cpp:206
a2dlist< a2dDumbPtr< a2dPin > > & GetConnectedPins()
Return list fo connected pins.
Definition: canpin.h:462
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
const a2dFont * a2dDEFAULT_CANVASFONT
global a2dFont stock object for default font
bool Undo()
Override this to undo a command.
Definition: wire.cpp:1386
virtual bool Submit(a2dCommand *command, bool storeIt=true)
Definition: drawing.cpp:5966
virtual void DoRender(a2dIterC &ic, OVERLAP clipparent)
Render derived object.
Definition: cantext.cpp:647
virtual bool FindConnectedPins(a2dCanvasObjectList &result, a2dPin *pin=NULL, bool walkWires=true, a2dPinClass *searchPinClass=NULL, a2dCanvasObject *isConnectedTo=NULL)
Find pins in other object which are connected to this object.
Definition: wire.cpp:1424
virtual void DoSave(wxObject *parent, a2dIOHandlerXmlSerOut &out, a2dXmlSer_flag xmlparts, a2dObjectList *towrite)
Write object specific CVG data.
Definition: cantext.cpp:568
virtual bool NeedsUpdateWhenConnected() const
used in case of flexible canvas objects (wires).
Definition: wire.cpp:401
used to release object from a a2dCanvasDocument in the current parent
Definition: drawing.h:1437
void DuplicateConnectedPins(a2dPin *other, bool undo=false)
pins connected to given other pin, will become part of this pin.
Definition: canpin.cpp:864
wxString GetName() const
get the name given to the pin.
Definition: canpin.h:322
a2dRestrictionEngine * GetRestrictionEngine()
Get restriction engine (grid snapping)
Definition: canglob.cpp:934
a2dConnectionGenerator * GetConnectionGenerator() const
Get class for generating new connection objects between object and pins.
Definition: canpin.h:723
double GetAbsAngle() const
get absolute angle of the pin ( after applying the parent its matrix and it own matrix ) ...
Definition: canpin.cpp:990
bool GetRelease() const
get release flag
Definition: gen.h:1350
a2dCanvasCommandProcessor * GetCanvasCommandProcessor()
get a pointer to the command processor
Definition: drawing.cpp:375
wire classes for connecting objects.
bool Undo()
Override this to undo a command.
Definition: wire.cpp:123
double GetWidth() const
returns width of the boundingbox
Definition: bbox.cpp:328
static a2dPinClass * Standard
Pins of this class can only connect to pins of the same class.
Definition: canpin.h:766
void SetPosXY(double x, double y, bool restrict=false)
set position to x,y
Definition: canobj.cpp:1624
if set, clone properties (e.g. fill style), otherwise ref-copy them
Definition: gen.h:1205
void SetPin(a2dPin *pin)
if handle is at the position of a pin, it can be set here, to make it easy moving it in sync with the...
Definition: polygon.h:787
bool m_editingCopy
true if the object needs to be rendered in edit mode.
Definition: candefs.h:304
void SetPinClass(a2dPinClass *pinClass)
Set the pin class.
Definition: canpin.h:359
if set, clone members (e.g. line end styles), otherwise ref-copy them
Definition: gen.h:1203
a2dPin * GetPin()
see SetPin()
Definition: polygon.h:789
base classes for tools and controller on top of the tools.
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
virtual bool FindConnectedPins(a2dCanvasObjectList &result, a2dPin *pin=NULL, bool walkWires=true, a2dPinClass *searchPinClass=NULL, a2dCanvasObject *isConnectedTo=NULL)
Find pins in other object which are connected to this object.
Definition: canobj.cpp:6586
void SetDynamicPin(bool dynamicPin)
set when pin is a dynamic pin
Definition: canpin.h:421
a2dCanvasObject * GetParent() const
Definition: wire.h:343
a2dPinClass * m_wireBegin
The pin class in the pin of the wire at the start of the wire.
Definition: wire.h:174
all polygon and polyline a2dCanvasObject are here.
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
double Length()
calculate length of path
Definition: polyver.cpp:1772
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.
a2dPinClass * m_wireEnd
The pin class in the pin of the wire at the end of the wire.
Definition: wire.h:175
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
virtual bool AdjustAfterChange(bool final)
Definition: wire.cpp:446
a2dPinClass * m_objBegin
The pin class in the pin of the object at the start of the wire.
Definition: wire.h:171
size_t GetNumberOfSegments()
get the number of points in the pointlist
Definition: polygon.h:229
a2dSnapToWhatMask GetSnapSourceFeatures() const
Definition: restrict.h:227
void GetPosXYSegment(int index, double &x, double &y, bool transform=true) const
get point x and y at index
Definition: polygon.cpp:605
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
void SetName(const wxString &name)
set the name of the pin (must be unique)
Definition: canpin.h:325
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
virtual void SetLayer(wxUint16 layer)
set layer index where this object is drawn upon.
Definition: canobj.cpp:5920
virtual bool IsConnect() const
return true, if this object is used to connect other object&#39;s using rubberband like structures...
Definition: canobj.h:1831
list of a2dObject&#39;s
Definition: gen.h:3157
#define BBOX2XYWH(bbox)
expand a2dBoundingBox to x,y,w,h
Definition: axis.cpp:885
void SetConnectionInfo(bool inverted, a2dPinClass *objBegin, a2dPinClass *objEnd)
Definition: wire.cpp:385
bool m_inverted
The wire is inverted (drawn from end to begin)
Definition: wire.h:180
CloneOptions
options for cloning
Definition: gen.h:1200
virtual bool DoStartEdit(wxUint16 editmode, wxEditStyle editstyle)
only used for editable objects and under control of a editing tool.
Definition: wire.cpp:1453
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
snap to pins in other objects
Definition: restrict.h:111
bool EliminateMatrix()
reduce matrix to identity without replacing object
Definition: polygon.cpp:812
a2dPin * SplitAtPin(a2dCanvasObject *parent, a2dPin *splitPin, a2dPin *splitPinClone=NULL, a2dWirePolylineL *clone=NULL, double hitMargin=a2dACCUR)
Split wire at pin given, and add the new split off wire part to parent, creates a new pin at split...
Definition: wire.cpp:501
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
bool Do()
Override this to perform a command.
Definition: wire.cpp:58
wxEditStyle
Definition: canobj.h:109
a base command for the a2dCommandProcessor
Definition: comevt.h:140
wire.cpp Source File -- Sun Oct 12 2014 17:04:26 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation