wxArt2D
route.cpp
Go to the documentation of this file.
1 /*! \file canvas/src/route.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/route.h"
22 #include "wx/canvas/wire.h"
23 #include "wx/canvas/canobj.h"
24 #include "wx/canvas/objlist.h"
25 #include "wx/canvas/canpin.h"
26 #include "wx/canvas/drawing.h"
27 
28 //#include "wx/genart/prfl.h"
29 //#include "wx/genart/prfltmr.h"
30 //#include "wx/genart/prflcntmean.h"
31 //#include "wx/genart/prflenbl.h"
32 
33 //#define DUMP_FINAL
34 
35 IMPLEMENT_CLASS( a2dRouteData, a2dObject );
36 
37 double a2dRouteData::m_raster = 4;
38 
40 {
41  m_mincostindex = 0;
42  memset( m_costring, 0, sizeof( m_costring ) );
43  m_freelist = 0;
44  m_memory = new AllocBlock();
45  m_memory->m_next = 0;
46  m_freememory = 0;
47 #ifdef _DEBUG
48  m_mincost = 0;
49 #endif
50 #ifdef PRFL_ENBL
51  m_count = 0;
52 #endif
53 }
54 
56 {
57  AllocBlock* current, *next;
58 
59  for( current = m_memory; current; current = next )
60  {
61  next = current->m_next;
62  delete current;
63  }
64 }
65 
67 {
68 #ifdef PRFL_ENBL
69  m_count++;
70 #endif
71 
72  // Allocate memory
73  BorderPoint* newobjc;
74 
75  if( m_freelist )
76  {
77  // an object in the free list
78  newobjc = m_freelist;
79  m_freelist = m_freelist->m_next;
80  }
81  else if( m_freememory < AllocBlock::m_pointsperblock )
82  {
83  // an object in the allocation block
84  newobjc = m_memory->m_memory + m_freememory;
85  m_freememory ++;
86  }
87  else
88  {
89  // create new allocation block
90  AllocBlock* newblock = new AllocBlock();
91  newblock->m_next = m_memory;
92  m_memory = newblock;
93  newobjc = m_memory->m_memory;
94  m_freememory = 1;
95  }
96 
97  // insert into allocation ring
98  *newobjc = brdr;
99 #ifdef _DEBUG
100  wxASSERT( brdr.m_cost - m_mincost < m_ncost );
101 #endif
102  int index = brdr.m_cost & m_costmask;
103  newobjc->m_next = m_costring[index];
104  m_costring[index] = newobjc;
105 
106  if( !m_costring[ m_mincostindex ] )
107  {
108  // This happens only the first time
109 #ifdef _DEBUG
110  wxASSERT( m_mincostindex == 0 && m_mincost == 0 );
111 #endif
112  m_mincostindex = index;
113 #ifdef _DEBUG
114  m_mincost = brdr.m_cost;
115 #endif
116  }
117 }
118 
120 {
121 #ifdef PRFL_ENBL
122  m_count--;
123 #endif
124 
125  // Get and remove best object
126  BorderPoint* obj = m_costring[ m_mincostindex ];
127  wxASSERT( obj );
128  m_costring[ m_mincostindex ] = obj->m_next;
129  // Insert into free list
130  obj->m_next = m_freelist;
131  m_freelist = obj;
132  // Increent cost
133  if( !m_costring[ m_mincostindex ] )
134  {
135  unsigned int i;
136  for( i = m_mincostindex; i < m_ncost; i++ )
137  {
138  if( m_costring[ i ] )
139  goto found;
140  }
141 
142  for( i = 0; i < m_mincostindex; i++ )
143  {
144  if( m_costring[ i ] )
145  goto found;
146  }
147 
148  // Queue is empty
149  m_mincostindex = 0;
150 #ifdef _DEBUG
151  m_mincost = 0;
152 #endif
153  return;
154 
155 found:;
156  m_mincostindex = i;
157 #ifdef _DEBUG
158  wxASSERT( m_costring[ m_mincostindex ] );
159  wxASSERT( m_costring[ m_mincostindex ]->m_cost > m_mincost );
160  wxASSERT( ( m_costring[ m_mincostindex ]->m_cost & m_costmask ) == m_mincostindex );
161  m_mincost = m_costring[ m_mincostindex ]->m_cost;
162 #endif
163  }
164 }
165 
166 a2dRouteData::a2dRouteData( a2dCanvasObject* showobject, bool final )
167 {
168  //PRFL_AUTO_TMR( RerouteInit );
169 
170 #ifdef DUMP_FINAL
171  m_dump = fopen( "Routerdump.txt", "w" );
172 #endif
173 
174  m_ok = true;
175  m_showobject = showobject;
176 
177  // Determine the raster size
178  a2dBoundingBox bbox;
179 
180  // Go through all direct childs of the show object and add them to the bounding box
181  a2dCanvasObjectList::iterator iter;
182  for( iter = m_showobject->GetChildObjectList()->begin(); iter != m_showobject->GetChildObjectList()->end(); ++iter )
183  {
184  a2dCanvasObject* obj = ( *iter );
185 
186  // toolobjects are not considered directly
187  // but if they are the editcopy of another object, they are
188  if( obj->GetAlgoSkip() && a2dCanvasObject::PROPID_ToolObject->GetPropertyValue( obj ) )
189  continue;
190 
191  // the editcopies are the objects that move around, so its new location is made part
192  // of the routing grid, because the newly routed wire has to reach to these objects.
193  a2dCanvasObject* editcopy = a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( obj );
194  if( !final && editcopy )
195  obj = editcopy;
196 
197  a2dBoundingBox objbbox = CalculateRoutingBbox( obj );
198  bbox.Expand( objbbox );
199  //wxLogDebug("Objc %d %p %p %lg %lg %lg %lg %s", final, obj, editcopy, objbbox.GetMinX(), objbbox.GetMaxX(), objbbox.GetMinY(), objbbox.GetMaxY(), obj->GetClassInfo()->GetClassName() );
200  }
201 
202  m_rasterborder = 20;
203  bbox.Enlarge( m_rasterborder );
204 
205  m_rasterinv = 1.0 / m_raster;
206  m_rasterminx = ( int ) floor( bbox.GetMinX() * m_rasterinv );
207  m_rastermaxx = ( int ) ceil( bbox.GetMaxX() * m_rasterinv );
208  m_rasterminy = ( int ) floor( bbox.GetMinY() * m_rasterinv );
209  m_rastermaxy = ( int ) ceil( bbox.GetMaxY() * m_rasterinv );
210 
211  // wxLogDebug("BBox %d %lg %lg %lg %lg", final, m_rasterminx, m_rastermaxx, m_rasterminy, m_rastermaxy );
212 
213  // Limit raster size to something reasonable
214  if( m_rastermaxx - m_rasterminx > 10000 )
215  {
216  m_ok = false;
217  return;
218  }
219  if( m_rastermaxy - m_rasterminy > 10000 )
220  {
221  m_ok = false;
222  return;
223  }
224 
225  // Allocate and clear memory
226  m_width = m_rastermaxx - m_rasterminx;
227  m_widthp1 = m_width + 1;
228  m_height = m_rastermaxy - m_rasterminy;
229  m_heightp1 = m_height + 1;
230 
231  m_verticaloccupation = new unsigned short[ m_widthp1 * m_heightp1 ];
232  m_horizontaloccupation = new unsigned short[ m_widthp1 * m_heightp1 ];
234 
236  {
237  m_ok = false;
238  return;
239  }
240 
241  memset( m_verticaloccupation, 0, m_widthp1 * m_heightp1 * sizeof( *m_verticaloccupation ) );
243  memset( m_routepoints, 0, m_widthp1 * m_heightp1 * dir_count * sizeof( *m_routepoints ) );
244 
245  //PRFL_CNT_MEAN( RerouteInitSize, m_widthp1 * m_heightp1 );
246 
247  // Go through all direct childs of the show object and add them to the occupation arrays
248  for( iter = m_showobject->GetChildObjectList()->begin(); iter != m_showobject->GetChildObjectList()->end(); ++iter )
249  {
250  a2dCanvasObject* obj = ( *iter );
251  // toolobjects are not considered directly
252  // but if they are the editcopy of another object, they are
253  if( obj->GetAlgoSkip() && a2dCanvasObject::PROPID_ToolObject->GetPropertyValue( obj ) )
254  continue;
255 
256  a2dCanvasObject* editcopy = a2dCanvasObject::PROPID_Editcopy->GetPropertyValue( obj );
257  // To prevent that the dragged objects (editcopies) get rerouted wires on top of themselfs.
258  if( !final && editcopy )
259  obj = editcopy;
260 
261  // wires that are to be rerouted are also not added
263  if( wire && wire->GetReroute() )
264  {
265  wire->SetRerouteAdded( false );
266  continue;
267  }
268 
269  if( wxDynamicCast( obj, a2dPolygonL ) )
270  {
271  AddOccupationPolyline( wxStaticCast( obj, a2dPolygonL )->GetSegments(), obj->GetTransformMatrix(), 1 );
272  }
273  else
274  {
275  a2dBoundingBox bbox = CalculateRoutingBbox( obj );
276  AddOccupationRect( bbox, 1 );
277  }
278  }
279 
280 #ifdef DUMP_FINAL
281  if( final )
282  {
283  fprintf( m_dump, "Route init\n" );
284  DumpOccupation( m_dump );
285  }
286 #endif
287 }
288 
290 {
291  delete [] m_verticaloccupation;
292  delete [] m_horizontaloccupation;
293  delete [] m_routepoints;
294 #ifdef DUMP_FINAL
295  //fclose( m_dump );
296 #endif
297 }
298 
299 // WX_DEFINE_SORTED_ARRAY( a2dRouteData::BorderPoint*, BorderQueue );
300 
302  BorderQueue* queue, RoutePoint* current,
303  int nextx, int nexty,
304  int dir, int prevdir
305 )
306 {
307  //PRFL_AUTO_TMR( AddBorderPoint );
308  //PRFL_CNT_MEAN( AddBorderPointC, queue->m_count );
309 
310  wxASSERT( nextx >= 0 && nextx <= m_width );
311  wxASSERT( nexty >= 0 && nexty <= m_height );
312  wxASSERT( dir >= dir_min && dir <= dir_max );
313  wxASSERT( prevdir >= dir_min && prevdir <= dir_max );
314 
315  RoutePoint* next = &GetRoutePoint( nextx, nexty, dir );
316  if( next->m_flags & flag_reachable )
317  {
318  return;
319  }
320 
321  // Don't go back to where we came from
322  if( ( dir ^ prevdir ) == dir_invxor )
323  {
324  return;
325  }
326 
327  BorderPoint border;
328 
329  border.m_x = nextx;
330  border.m_y = nexty;
331  border.m_direction = dir;
332  border.m_prevdir = prevdir;
333 
334  border.m_cost = current->m_cost;
335 
336  if( next->m_flags & flag_original )
337  {
338  // general path cost for points along the original wire
339  border.m_cost += 1;
340  }
341  else
342  {
343  // general path cost for points not along the original wire
344  border.m_cost += 3;
345  }
346 
347  // extra path cost for corners
348  if(
349  // either point is non-original
350  !( ( current->m_flags & flag_original ) && ( next->m_flags & flag_original ) ) &&
351  // and this is a corner
352  current->m_direction != border.m_direction
353  )
354  {
355  border.m_cost += 10;
356  }
357 
358  // extra path cost for crossing occupied areas
359  if( IsHorizontalOccupied( nextx, nexty ) || IsVerticalOccupied( nextx, nexty ) )
360  {
361  border.m_cost += 10;
362  }
363 
364  queue->Add( border );
365 }
366 
367 bool a2dRouteData::RerouteWire( a2dWirePolylineL* wire, a2dPin* dispin, a2dPin* startpin, bool startisbegin, bool final )
368 {
369  a2dPin* maxDisLocated = dispin->IsDislocated();
370 
371  // Note on parameteres:
372  // startpin may be Null if a wire was half routed
373 
374  // wxLogDebug("Route %p %d", wire, wire->GetSegments()->GetCount() );
375 
376  //PRFL_AUTO_TMR( RerouteWire );
377  if( !m_ok )
378  {
379  return false;
380  }
381 
382  // Clear routing point data
383  memset( m_routepoints, 0, m_widthp1 * m_heightp1 * dir_count * sizeof( *m_routepoints ) );
384 
385  /* This is for dumping the last pre-final and the final route
386  After the first routing you have 2 seconds to get close to final, then after
387  2 seconds make a final move and release the mouse
388  static clock_t start = clock();
389  if( clock()-start > 2000 || final )
390  {
391  wxLogDebug("Route %p %d", wire, final );
392  DumpOccupation();
393  }
394  */
395 
396 #ifdef DUMP_FINAL
397  if( final )
398  {
399  fprintf( m_dump, "Route Final 1 %p %d\n", wire, wire->GetSegments()->GetCount() );
400  DumpOccupation( m_dump );
401  }
402 #endif
403 
404  //PRFL_BGN_TMR( RerouteWireInit );
405  // Set the original flags for all points on the wire
406  SetFlagPolyline( wire->GetSegments(), wire->GetTransformMatrix(), flag_original );
407 
408  // Set the wire as not occupied
409  if( wire->GetRerouteAdded() )
410  {
411  AddOccupationPolyline( wire->GetSegments(), wire->GetTransformMatrix(), -1 );
412  }
413 
414  a2dBoundingBox bboxStartPin;
415  a2dBoundingBox bboxDisPin;
416 
417  //if a connected pin is internal, make sure that the parent of that object is not occupied.
418  //This here works for original and editcopies, because for editcopies a a2dWireEnd,
419  //instead of the real object which is there,
420  //is added at the ends of the non editing objects which are indirectly connected via wires.
421  //Wires itself are already non occupied.
422  //In case of a a2dWireEnd the original object is found via the property PROPID_Original.
423  if ( startpin && startpin->IsConnectedTo() && startpin->IsConnectedTo()->IsInternal() )
424  {
425  a2dWireEnd* end = wxDynamicCast( startpin->IsConnectedTo()->GetParent(), a2dWireEnd );
426  if ( end )
427  {
428  a2dCanvasObject* org = a2dCanvasObject::PROPID_Original->GetPropertyValue( end );
429  bboxStartPin = CalculateRoutingBbox( org );
430  }
431  else
432  {
433  bboxStartPin = CalculateRoutingBbox( startpin->IsConnectedTo()->GetParent() );
434  }
435  AddOccupationRect( bboxStartPin, -1 );
436  }
437 
438  if ( maxDisLocated && maxDisLocated->IsInternal() )
439  {
440  a2dWireEnd* end = wxDynamicCast( maxDisLocated->GetParent(), a2dWireEnd );
441  if ( end )
442  {
443  a2dCanvasObject* org = a2dCanvasObject::PROPID_Original->GetPropertyValue( end );
444  bboxDisPin = CalculateRoutingBbox( org );
445  }
446  else
447  {
448  bboxDisPin = CalculateRoutingBbox( maxDisLocated->GetParent() );
449  }
450  AddOccupationRect( bboxDisPin, -1 );
451  }
452 
453  // Check if the target pin is at an exact grid location
454  a2dPoint2D targetpos = maxDisLocated->GetAbsXY();
455 
456  // TARGET is where to route the wire needs to route to.
457  // Check if the target is a wire
458  if( wxDynamicCast( maxDisLocated->GetParent(), a2dWirePolylineL ) )
459  {
460  // Target is a wire
461  a2dWirePolylineL* target = wxStaticCast( maxDisLocated->GetParent(), a2dWirePolylineL );
462 
463  SetFlagPolyline( target->GetSegments(), target->GetTransformMatrix(), flag_targetwire );
464  }
465  else if( startpin && startpin->IsConnectedTo() && wxDynamicCast( startpin->IsConnectedTo()->GetParent(), a2dWirePolylineL ) )
466  {
468 
469  // we start on a wire to an object, so routing in reverse direction is usually better
470  // because we have more freedom, so swap the route
471  a2dPin* h;
472  h = dispin;
473  dispin = startpin;
474  startpin = h;
475  startisbegin = !startisbegin;
476 
477  // The startpin (was dispin) is dislocated, so first relocate it
478  // Get the wire local coordinate of the new position of the start pin
479  a2dPoint2D newstartpos = maxDisLocated->GetAbsXY();
480 
481  // target was switched with startpin, but maybe startpin was not dislocated at all, so take the best choice.
482  h = dispin->IsDislocated();
483  if ( h )
484  targetpos = h->GetAbsXY();
485  else
486  targetpos = dispin->IsConnectedTo()->GetAbsXY();
487 
488  a2dAffineMatrix trns = wire->GetTransformMatrix();
489  trns.Invert();
490  trns.TransformPoint( &newstartpos );
491  // Set this position to the start pin
492  if ( target->GetRoot()->GetCommandProcessor() && final )
493  target->GetRoot()->GetCommandProcessor()->Submit(
494  new a2dCommand_SetCanvasProperty( startpin, a2dCanvasObject::PROPID_Position, newstartpos, -1, true ), final );
495  else
496  startpin->SetPosXyPoint( newstartpos );
497 
498  SetFlagPolyline( target->GetSegments(), target->GetTransformMatrix(), flag_targetwire );
499  }
500 
501  if(
502  floor( targetpos.m_x * m_rasterinv ) * m_raster == targetpos.m_x &&
503  floor( targetpos.m_y * m_rasterinv ) * m_raster == targetpos.m_y
504  )
505  {
506  // Pin is at exact raster location
507  int x = ( int ) floor( ( targetpos.m_x + 0.5 * m_raster ) * m_rasterinv ) - m_rasterminx;
508  int y = ( int ) floor( ( targetpos.m_y + 0.5 * m_raster ) * m_rasterinv ) - m_rasterminy;
509  SetFlagRoutePointAllDirs( x, y, flag_targetpin );
510  }
511  else
512  {
513  // Approximate raster location
514  int x1 = ( int ) floor( targetpos.m_x * m_rasterinv ) - m_rasterminx;
515  int y1 = ( int ) floor( targetpos.m_y * m_rasterinv ) - m_rasterminy;
516  int x2 = ( int ) ceil( targetpos.m_x * m_rasterinv ) - m_rasterminx;
517  int y2 = ( int ) ceil( targetpos.m_y * m_rasterinv ) - m_rasterminy;
518  SetFlagRoutePointAllDirs( x1, y1, flag_targetapprox );
519  SetFlagRoutePointAllDirs( x2, y1, flag_targetapprox );
520  SetFlagRoutePointAllDirs( x1, y2, flag_targetapprox );
521  SetFlagRoutePointAllDirs( x2, y2, flag_targetapprox );
522  }
523 
524 #ifdef DUMP_FINAL
525  if( final )
526  {
527  fprintf( m_dump, "Route Final 2 %p %d\n", wire, wire->GetSegments()->GetCount() );
528  DumpOccupation( m_dump );
529  }
530 #endif
531 
532  // Start routing
533  a2dPoint2D startpos;
534  if( !startpin )
535  {
536  // There might be no startpin when a wire is dangling
537  // In this case use wire vertex coordinates
538  startpos = startisbegin ? wire->GetSegments()->front()->GetPoint() : wire->GetSegments()->back()->GetPoint();
539  wire->GetTransformMatrix().TransformPoint( &startpos );
540  }
541  else
542  {
543  startpos = startpin->GetAbsXY();
544  }
545 
546  int startx = ( int ) floor( ( startpos.m_x + 0.5 * m_raster ) * m_rasterinv ) - m_rasterminx;
547  int starty = ( int ) floor( ( startpos.m_y + 0.5 * m_raster ) * m_rasterinv ) - m_rasterminy;
548 
549  BorderQueue queue;
550 
551  for( int dir = dir_min; dir <= dir_max; dir++ )
552  {
553  BorderPoint start;
554  start.m_x = startx;
555  start.m_y = starty;
556  start.m_direction = dir;
557  start.m_prevdir = dir_start;
558  start.m_cost = 0;
559 
560  queue.Add( start );
561  }
562 
563  RoutePoint* end = 0;
564 
565  //PRFL_END_TMR( RerouteWireInit );
566 
567  while( queue.IsNotEmpty() )
568  {
569  // Get current minimum cost point
570  const BorderPoint& border = queue.GetBest();
571 
572  RoutePoint* point = &GetRoutePoint( border.m_x, border.m_y, border.m_direction );
573 
574  if( point->m_flags & flag_reachable )
575  {
576  // The point was already reached at lower cost
577  queue.RmvBest();
578  continue;
579  }
580 
581  point->m_x = border.m_x;
582  point->m_y = border.m_y;
583  point->m_direction = border.m_direction;
584  point->m_prevdir = border.m_prevdir;
585  point->m_cost = border.m_cost;
586 
587  // Check if we reached a target point
588  if( point->m_flags & ( flag_targetwire | flag_targetpin | flag_targetapprox ) )
589  {
590  // Ok, target reached
591  end = point;
592  break;
593  }
594 
595  // Check occupation of this point depending on direction
596  if( border.m_prevdir != dir_start )
597  {
598  switch( border.m_direction )
599  {
600  case dir_xminus:
601  case dir_xplus:
602  if( IsHorizontalOccupied( border.m_x, border.m_y ) )
603  {
604  // The point is occupied in this direction
605  queue.RmvBest();
606  continue;
607  }
608  break;
609  case dir_yminus:
610  case dir_yplus:
611  if( IsVerticalOccupied( border.m_x, border.m_y ) )
612  {
613  // The point is occupied in this direction
614  queue.RmvBest();
615  continue;
616  }
617  break;
618  }
619  }
620 
621  // the point is reachable
622  point->m_flags |= flag_reachable;
623 
624  //PRFL_BGN_TMR( RerouteWireAddBlock );
625 
626  if( !IsVerticalOccupied( point->m_x, point->m_y ) || border.m_prevdir == dir_start )
627  {
628  // Check going into Y- (top) direction
629  // The dir_xxx given is the direction of source viewed from the target, so it is inverse
630  if( point->m_y > 0 )
631  {
633  &queue, point,
634  point->m_x, point->m_y - 1,
635  dir_yplus, point->m_direction
636  );
637  }
638 
639  // Check going into Y+ (bottom) direction
640  // The dir_xxx given is the direction of source viewed from the target, so it is inverse
641  if( point->m_y < m_height )
642  {
644  &queue, point,
645  point->m_x, point->m_y + 1,
646  dir_yminus, point->m_direction
647  );
648  }
649  }
650 
651  if( !IsHorizontalOccupied( point->m_x, point->m_y ) || border.m_prevdir == dir_start )
652  {
653  // Check going into X- (left) direction
654  // The dir_xxx given is the direction of source viewed from the target, so it is inverse
655  if( point->m_x > 0 )
656  {
658  &queue, point,
659  point->m_x - 1, point->m_y,
660  dir_xplus, point->m_direction
661  );
662  }
663 
664  // Check going into X+ (right) direction
665  // The dir_xxx given is the direction of source viewed from the target, so it is inverse
666  if( point->m_x < m_width )
667  {
669  &queue, point,
670  point->m_x + 1, point->m_y,
671  dir_xminus, point->m_direction
672  );
673  }
674  }
675 
676  //PRFL_END_TMR( RerouteWireAddBlock );
677 
678  wxASSERT( &queue.GetBest() == &border );
679  queue.RmvBest();
680  }
681 
682  // queue.Clear();
683 
684 #ifdef DUMP_FINAL
685  if( final )
686  {
687  fprintf( m_dump, "Route Final 3 %p %d\n", wire, wire->GetSegments()->GetCount() );
688  DumpOccupation( m_dump );
689  }
690 #endif
691 
692  if ( bboxStartPin.GetValid() )
693  {
694  AddOccupationRect( bboxStartPin, 1 );
695  }
696 
697  if ( bboxDisPin.GetValid() )
698  {
699  AddOccupationRect( bboxDisPin, 1 );
700  }
701 
702  if( !end )
703  {
704  //wxLogDebug( "missed" );
705  // Target not reached => create a straight line wire
706  a2dVertexList* newpoints = new a2dVertexList;
707  if( startisbegin )
708  {
709  newpoints->push_back( new a2dLineSegment( startpos ) );
710  newpoints->push_back( new a2dLineSegment( targetpos ) );
711  }
712  else
713  {
714  newpoints->push_back( new a2dLineSegment( targetpos ) );
715  newpoints->push_back( new a2dLineSegment( startpos ) );
716  }
717  // Adjust the existing vertex list to the new vertex list
718  if ( wire->GetRoot()->GetCommandProcessor() && final )
719  wire->GetRoot()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), final );
720  else
721  wire->SetSegments( newpoints );
722 
723  // Set the wire as occupied, to prevent other wires that will still be rerouted, are reroute on top.
725  wire->SetRerouteAdded( true );
726  return false;
727  }
728  else
729  {
730  //wxLogDebug( "oke" );
731  // Create a new vertex list for the wire
732  a2dVertexList* newpoints = new a2dVertexList;
733  RoutePoint* current = end;
734  int prevdir = -1;
735 
736  a2dPoint2D endpoint( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
737 
738  if( end->m_flags & flag_targetapprox )
739  {
740  // Target is only approximate, so add a point at the real target
741  if( startisbegin )
742  newpoints->push_front( new a2dLineSegment( targetpos ) );
743  else
744  newpoints->push_back( new a2dLineSegment( targetpos ) );
745 
746  // Add extra point, to avoid 45 degree line pieces
747  a2dLineSegment* p = NULL;
748  a2dPoint2D point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
749  if ( current->m_direction == dir_xminus || current->m_direction == dir_xplus )
750  {
751  if ( point.m_y != targetpos.m_y )
752  p = new a2dLineSegment( targetpos.m_x, point.m_y );
753  prevdir = current->m_direction;
754  }
755  else if ( current->m_direction == dir_yminus || current->m_direction == dir_yplus )
756  {
757  if ( point.m_x != targetpos.m_x )
758  p = new a2dLineSegment( point.m_x, targetpos.m_y );
759  prevdir = current->m_direction;
760  }
761  if ( p )
762  {
763  if( startisbegin )
764  newpoints->push_front( p );
765  else
766  newpoints->push_back( p );
767  }
768  }
769  else if( end->m_flags & flag_targetwire )
770  {
771  // If this doesn't fit exactly, insert a line
772  a2dPoint2D dispinpos = targetpos;
773 
774  if( dispinpos != endpoint )
775  {
776  if( startisbegin )
777  newpoints->push_front( new a2dLineSegment( dispinpos ) );
778  else
779  newpoints->push_back( new a2dLineSegment( dispinpos ) );
780 
781  // Add extra point, to avoid 45 degree line pieces
782  a2dLineSegment* p = NULL;
783  a2dPoint2D point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
784  if ( current->m_direction == dir_xminus || current->m_direction == dir_xplus )
785  {
786  if ( point.m_y != dispinpos.m_y )
787  p = new a2dLineSegment( dispinpos.m_x, point.m_y );
788  prevdir = current->m_direction;
789  }
790  else if ( current->m_direction == dir_yminus || current->m_direction == dir_yplus )
791  {
792  if ( point.m_x != dispinpos.m_x )
793  p = new a2dLineSegment( point.m_x, dispinpos.m_y );
794  prevdir = current->m_direction;
795  }
796  if ( p )
797  {
798  if( startisbegin )
799  newpoints->push_front( p );
800  else
801  newpoints->push_back( p );
802  }
803  }
804  }
805 
806 
807  //reconstruct poinst from route path found.
808  for( ;; )
809  {
810  current->m_flags |= flag_final;
811 
812  a2dLineSegment point( ( current->m_x + m_rasterminx ) * m_raster, ( current->m_y + m_rasterminy ) * m_raster );
813 
814  if( current->m_prevdir == dir_start )
815  {
816  //reached the special marked point, with direction dir_start.
817  if( startisbegin )
818  newpoints->push_front( new a2dLineSegment( point ) );
819  else
820  newpoints->push_back( new a2dLineSegment( point ) );
821 
822  // at the beginning the startpin location was rounded to the grid.
823  // if the startpin was not on the grid, add an extra segment to reach it.
824  if( startpin )
825  {
826  if (
827  floor( point.m_x * m_rasterinv ) * m_raster == startpin->GetPosX() &&
828  floor( point.m_y * m_rasterinv ) * m_raster == startpin->GetPosY()
829  )
830  {
831  //DONE reconstruction of wire from routing points.
832  }
833  else
834  {
835  if( startisbegin )
836  newpoints->push_front( new a2dLineSegment( startpin->GetPosX(), startpin->GetPosY() ) );
837  else
838  newpoints->push_back( new a2dLineSegment( startpin->GetPosX(), startpin->GetPosY() ) );
839  }
840  }
841  break;
842  }
843 
844  if( current->m_direction != prevdir )
845  {
846  if( startisbegin )
847  newpoints->push_front( new a2dLineSegment( point ) );
848  else
849  newpoints->push_back( new a2dLineSegment( point ) );
850  prevdir = current->m_direction;
851  }
852 
853  int x = current->m_x;
854  int y = current->m_y;
855  switch( current->m_direction )
856  {
857  case dir_xminus:
858  x--;
859  break;
860  case dir_xplus:
861  x++;
862  break;
863  case dir_yminus:
864  y--;
865  break;
866  case dir_yplus:
867  y++;
868  break;
869  }
870 
871  current = &GetRoutePoint( x, y, current->m_prevdir );
872  }
873 
874  // Adjust the existing vertex list to the new vertex list
875  if ( wire->GetRoot()->GetCommandProcessor() && final )
876  wire->GetRoot()->GetCommandProcessor()->Submit( new a2dCommand_SetSegments( wire, newpoints, true ), final );
877  else
878  wire->SetSegments( newpoints );
879  wire->SetPending( true );
880 
881  // Set the wire as occupied, to prevent other wires that will still be rerouted, are reroute on top.
883  wire->SetRerouteAdded( true );
884 
885 #ifdef DUMP_FINAL
886  if( final )
887  {
888  fprintf( m_dump, "Route Final 4 %p %d\n", wire, wire->GetSegments()->GetCount() );
889  DumpOccupation( m_dump );
890  }
891 #endif
892 
893  return true;
894  }
895 }
896 
897 void a2dRouteData::AddOccupationRect( const a2dBoundingBox& bbox, short incr )
898 {
899  int minx = ( int ) floor( ( bbox.GetMinX() + 0.75 * m_raster ) * m_rasterinv );
900  int maxx = ( int ) ceil ( ( bbox.GetMaxX() - 0.75 * m_raster ) * m_rasterinv );
901  int miny = ( int ) floor( ( bbox.GetMinY() + 0.75 * m_raster ) * m_rasterinv );
902  int maxy = ( int ) ceil ( ( bbox.GetMaxY() - 0.75 * m_raster ) * m_rasterinv );
903 
904  if( minx < m_rasterminx ) minx = m_rasterminx;
905  if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
906  if( miny < m_rasterminy ) miny = m_rasterminy;
907  if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
908 
909  int minxi = ( minx - m_rasterminx );
910  int maxxi = ( maxx - m_rasterminx );
911  int minyi = ( miny - m_rasterminy );
912  int maxyi = ( maxy - m_rasterminy );
913 
914  int x, y;
915 
916  for( y = minyi; y <= maxyi; y++ )
917  {
918  for( x = minxi; x <= maxxi; x++ )
919  {
920  unsigned short& h = GetHorizontalOccupation( x, y );
921  unsigned short& v = GetVerticalOccupation( x, y );
922  if ( incr < 0 )
923  {
924  // Klaas If this is a problem,fix it.
925  // < 0 should be possible, to keep track of the number of time not occupied!
926  //wxASSERT( h >= -incr && v >= -incr );
927  }
928  h += incr;
929  v += incr;
930  }
931  }
932 }
933 
934 void a2dRouteData::AddOccupationPolyline( const a2dVertexList* points, const a2dAffineMatrix& trns, short incr )
935 {
936  a2dVertexList::const_iterator iter = points->begin();
937  a2dVertexList::const_iterator prev = iter;
938  iter++;
939 
940  for( ; iter != points->end(); ++iter )
941  {
942  double x1l = ( *prev )->m_x;
943  double y1l = ( *prev )->m_y;
944  double x2l = ( *iter )->m_x;
945  double y2l = ( *iter )->m_y;
946  double x1, y1, x2, y2;
947 
948  trns.TransformPoint( x1l, y1l, x1, y1 );
949  trns.TransformPoint( x2l, y2l, x2, y2 );
950 
951  int minx = ( int ) floor( ( wxMin( x1, x2 ) + 0.5 * m_raster ) * m_rasterinv );
952  int maxx = ( int ) ceil ( ( wxMax( x1, x2 ) - 0.5 * m_raster ) * m_rasterinv );
953  int miny = ( int ) floor( ( wxMin( y1, y2 ) + 0.5 * m_raster ) * m_rasterinv );
954  int maxy = ( int ) ceil ( ( wxMax( y1, y2 ) - 0.5 * m_raster ) * m_rasterinv );
955 
956  if( minx < m_rasterminx ) minx = m_rasterminx;
957  if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
958  if( miny < m_rasterminy ) miny = m_rasterminy;
959  if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
960 
961  int minxi = ( minx - m_rasterminx );
962  int maxxi = ( maxx - m_rasterminx );
963  int minyi = ( miny - m_rasterminy );
964  int maxyi = ( maxy - m_rasterminy );
965 
966  if( minxi == maxxi )
967  {
968  // vertical line
969  for( int y = minyi; y <= maxyi; y++ )
970  {
971  GetVerticalOccupation( minxi, y ) += incr;
972  }
973  }
974  else if( minyi == maxyi )
975  {
976  // horizontal line
977  for( int x = minxi; x <= maxxi; x++ )
978  {
979  GetHorizontalOccupation( x, minyi ) += incr;
980  }
981  }
982  // Diagonal lines don't accupy anything
983 
984  prev = iter;
985  }
986 }
987 
989 {
990  int minx = ( int ) floor( ( bbox.GetMinX() + 0.5 * m_raster ) * m_rasterinv );
991  int maxx = ( int ) ceil ( ( bbox.GetMaxX() - 0.5 * m_raster ) * m_rasterinv );
992  int miny = ( int ) floor( ( bbox.GetMinY() + 0.5 * m_raster ) * m_rasterinv );
993  int maxy = ( int ) ceil ( ( bbox.GetMaxY() - 0.5 * m_raster ) * m_rasterinv );
994 
995  if( minx < m_rasterminx ) minx = m_rasterminx;
996  if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
997  if( miny < m_rasterminy ) miny = m_rasterminy;
998  if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
999 
1000  int minxi = ( minx - m_rasterminx );
1001  int maxxi = ( maxx - m_rasterminx );
1002  int minyi = ( miny - m_rasterminy );
1003  int maxyi = ( maxy - m_rasterminy );
1004 
1005  int x, y;
1006 
1007  for( y = minyi; y <= maxyi; y++ )
1008  {
1009  for( x = minxi; x <= maxxi; x++ )
1010  {
1011  SetFlagRoutePointAllDirs( x, y, flag );
1012  }
1013  }
1014 }
1015 
1017 {
1018  a2dVertexList::const_iterator iter = points->begin();
1019  a2dVertexList::const_iterator prev = iter;
1020  iter++;
1021 
1022  for( ; iter != points->end(); ++iter )
1023  {
1024  // klion: warning C4189: 'obj' : local variable is initialized but not referenced
1025  // a2dLineSegment *obj = (*iter);
1026 
1027  double x1l = ( *prev )->m_x;
1028  double y1l = ( *prev )->m_y;
1029  double x2l = ( *iter )->m_x;
1030  double y2l = ( *iter )->m_y;
1031  double x1, y1, x2, y2;
1032 
1033  trns.TransformPoint( x1l, y1l, x1, y1 );
1034  trns.TransformPoint( x2l, y2l, x2, y2 );
1035 
1036  //calculate the bbox of the line segment in raster coordinates.
1037  int minx = ( int ) floor( ( wxMin( x1, x2 ) + 0.5 * m_raster ) * m_rasterinv );
1038  int maxx = ( int ) ceil ( ( wxMax( x1, x2 ) - 0.5 * m_raster ) * m_rasterinv );
1039  int miny = ( int ) floor( ( wxMin( y1, y2 ) + 0.5 * m_raster ) * m_rasterinv );
1040  int maxy = ( int ) ceil ( ( wxMax( y1, y2 ) - 0.5 * m_raster ) * m_rasterinv );
1041 
1042  if( minx < m_rasterminx ) minx = m_rasterminx;
1043  if( maxx > m_rastermaxx ) maxx = m_rastermaxx;
1044  if( miny < m_rasterminy ) miny = m_rasterminy;
1045  if( maxy > m_rastermaxy ) maxy = m_rastermaxy;
1046 
1047  int minxi = ( minx - m_rasterminx );
1048  int maxxi = ( maxx - m_rasterminx );
1049  int minyi = ( miny - m_rasterminy );
1050  int maxyi = ( maxy - m_rasterminy );
1051 
1052  if( minxi == maxxi )
1053  {
1054  // vertical line
1055  for( int y = minyi; y <= maxyi; y++ )
1056  {
1057  SetFlagRoutePointAllDirs( minxi, y, flag );
1058  }
1059  }
1060  else if( minyi == maxyi )
1061  {
1062  // horizontal line
1063  for( int x = minxi; x <= maxxi; x++ )
1064  {
1065  SetFlagRoutePointAllDirs( x, minyi, flag );
1066  }
1067  }
1068  // Diagonal lines don't occupy anything
1069 
1070  prev = iter;
1071  }
1072 }
1073 
1075 {
1076  // This is not quite optimal.
1077  // It would probably be best to have a flag parameter to GetCalculatedBbox
1078  a2dBoundingBox box = object->GetUnTransformedBbox( false );
1079 
1081  {
1082  a2dCanvasObject* obj = *iter;
1083  if( !wxDynamicCast( obj, a2dPin ) )
1084  {
1085  box.Expand( obj->GetCalculatedBoundingBox( 0 ) );
1086  }
1087  }
1088 
1089  box.MapBbox( object->GetTransformMatrix() );
1090 
1091  return box;
1092 
1093 }
1094 
1095 
1097 {
1098 #ifdef _DEBUG
1099  if( file )
1100  fprintf( file, "\nOccupation %d x %d\n", m_width, m_height );
1101  else
1102  wxLogDebug( _T( "\nOccupation %d x %d" ), m_width, m_height );
1103 
1104  int x, y;
1105 
1106  wxChar* buffer = new wxChar [ m_widthp1 * 2 + 1 ];
1107  wxChar* pos;
1108 
1109  for( y = 0; y <= m_height; y++ )
1110  {
1111  // First Dump horizontal edges and points
1112  pos = buffer;
1113  for( x = 0; x <= m_width; x++ )
1114  {
1115  unsigned short ho = GetHorizontalOccupation( x, y );
1116  unsigned short vo = GetVerticalOccupation( x, y );
1117  RoutePoint* point0 = &GetRoutePoint( x, y, 0 );
1118  RoutePoint* point1 = &GetRoutePoint( x, y, 1 );
1119  RoutePoint* point2 = &GetRoutePoint( x, y, 2 );
1120  RoutePoint* point3 = &GetRoutePoint( x, y, 3 );
1121 
1122  if( ho == 0 && vo == 0 )
1123  *pos++ = wxT( '.' );
1124  else if( ho == 1 && vo == 0 )
1125  *pos++ = wxT( '-' );
1126  else if( ho == 0 && vo == 1 )
1127  *pos++ = wxT( '|' );
1128  else if( ho == 1 && vo == 1 )
1129  *pos++ = wxT( 'x' );
1130  else if( ho == 2 && vo == 0 )
1131  *pos++ = wxT( '=' );
1132  else if( ho == 0 && vo == 2 )
1133  *pos++ = wxT( '"' );
1134  else
1135  *pos++ = wxT( 'X' );
1136 
1137  if(
1138  ( point0->m_flags & flag_final ) ||
1139  ( point1->m_flags & flag_final ) ||
1140  ( point2->m_flags & flag_final ) ||
1141  ( point3->m_flags & flag_final )
1142  )
1143  *pos++ = wxT( '#' );
1144  else if( point0->m_flags & flag_targetpin )
1145  *pos++ = wxT( 'P' );
1146  else if( point0->m_flags & flag_targetapprox )
1147  *pos++ = wxT( 'A' );
1148  else if( point0->m_flags & flag_targetwire )
1149  *pos++ = wxT( 'W' );
1150  else if(
1151  ( point0->m_flags & flag_reachable ) ||
1152  ( point1->m_flags & flag_reachable ) ||
1153  ( point2->m_flags & flag_reachable ) ||
1154  ( point3->m_flags & flag_reachable )
1155  )
1156  *pos++ = wxT( 'R' );
1157  else
1158  *pos++ = wxT( ' ' );
1159  }
1160  *pos++ = 0;
1161  if( file )
1162  fprintf( file, "%s\n", buffer );
1163  else
1164  wxLogDebug( buffer );
1165  }
1166 
1167  delete [] buffer;
1168 #endif
1169 }
1170 
1171 void a2dRouteData::DumpCost()
1172 {
1173 #ifdef _DEBUG
1174  wxLogDebug( _T( "\nCost" ) );
1175  int x, y;
1176 
1177  wxChar* buffer = new wxChar [ m_widthp1 * 3 * 2 + 1 ];
1178  wxChar* pos;
1179 
1180  for( y = 0; y <= m_height; y++ )
1181  {
1182  pos = buffer;
1183  for( x = 0; x <= m_width; x++ )
1184  {
1185  RoutePoint* point = &GetRoutePoint( x, y, dir_xminus );
1186  int val = point->m_cost;
1187 
1188  *pos++ = val / 10 % 10 + wxT( '0' );
1189  *pos++ = val % 10 + wxT( '0' );
1190  *pos++ = wxT( ' ' );
1191 
1192  point = &GetRoutePoint( x, y, dir_yminus );
1193  val = point->m_cost;
1194 
1195  *pos++ = val / 10 % 10 + wxT( '0' );
1196  *pos++ = val % 10 + wxT( '0' );
1197  *pos++ = wxT( '|' );
1198  }
1199  *pos++ = 0;
1200  wxLogDebug( buffer );
1201 
1202  pos = buffer;
1203  for( x = 0; x <= m_width; x++ )
1204  {
1205  RoutePoint* point = &GetRoutePoint( x, y, dir_yplus );
1206  int val = point->m_cost;
1207 
1208  *pos++ = val / 10 % 10 + wxT( '0' );
1209  *pos++ = val % 10 + wxT( '0' );
1210  *pos++ = wxT( ' ' );
1211 
1212  point = &GetRoutePoint( x, y, dir_xplus );
1213  val = point->m_cost;
1214 
1215  *pos++ = val / 10 % 10 + wxT( '0' );
1216  *pos++ = val % 10 + wxT( '0' );
1217  *pos++ = wxT( '|' );
1218  }
1219  *pos++ = 0;
1220  wxLogDebug( buffer );
1221  wxLogDebug( _T( "" ) );
1222  }
1223 
1224  delete [] buffer;
1225 #endif
1226 }
1227 
1228 void a2dRouteData::DumpVertexList( a2dVertexList* list )
1229 {
1230 #ifdef _DEBUG
1231  wxLogDebug( wxT( "VertexList" ) );
1232  forEachIn( a2dVertexList, list )
1233  {
1234  wxLogDebug( wxT( "%12.3lf %12.3lf" ), ( *iter )->m_x, ( *iter )->m_y );
1235  }
1236 #endif
1237 };
1238 
1239 
unsigned short * m_horizontaloccupation
occupation counts for horizontal edges ( a 2d array )
Definition: route.h:369
wxPoint2DDouble a2dPoint2D
this to define if coordinate numbers are integer or doubles
Definition: artglob.h:47
This is a priority queue for border points.
Definition: route.h:174
a2dPin * IsDislocated() const
Definition: canpin.cpp:1089
RoutePoint * m_routepoints
Routing points.
Definition: route.h:371
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
double m_rasterborder
an extra border in the raster area around the bounding box
Definition: route.h:364
unsigned short & GetHorizontalOccupation(int x, int y)
Get an element of the horizontal occupation array.
Definition: route.h:250
void Add(const BorderPoint &brdr)
Add a border object.
Definition: route.cpp:66
const a2dAffineMatrix & GetTransformMatrix() const
get the matrix used to position the object
Definition: canobj.h:500
AllocBlock * m_memory
Current memory allocation block.
Definition: route.h:226
result of dir1^dir2 for two opposing directions
Definition: route.h:124
unsigned short m_x
coordinates of this point
Definition: route.h:160
a2dPin is used in a2dCanvasObject to add pins to it.
Definition: canpin.h:233
polygon defined with list of points.
Definition: polygon.h:45
static a2dPropertyIdVoidPtr * PROPID_ToolObject
set for objects that act as tool object, when a tool is in action.
Definition: canobj.h:2678
Ref Counted base object.
Definition: gen.h:1045
a2dDrawing * GetRoot() const
get a2dCanvasDocument of the object.
Definition: canobj.h:952
void Enlarge(const double Marge)
enlarge with the given amount
Definition: bbox.cpp:162
BorderPoint * m_next
pointer to the next point with same cost in the queue or to a free point
Definition: route.h:162
a2dBoundingBox GetCalculatedBoundingBox(int nChildLevels)
Like GetBbox, but it always calculcates the bounding box from scratch.
Definition: canobj.cpp:5072
An entry in the border queue.
Definition: route.h:151
virtual void SetPending(bool pending)
set this object pending for update
Definition: canobj.cpp:2585
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.
BorderPoint * m_costring[m_ncost]
The starting points of the cost lists.
Definition: route.h:222
void AddOccupationPolyline(const a2dVertexList *points, const a2dAffineMatrix &trns, short incr)
add a polyline to the occupation area
Definition: route.cpp:934
void SetFlagRoutePointAllDirs(int x, int y, RoutePointFlag flag)
Set a flag in the route points for all directions.
Definition: route.h:307
const BorderPoint & GetBest()
Get the best border point.
Definition: route.h:184
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
routing of wires.
BorderQueue()
constructor
Definition: route.cpp:39
min usual direction value
Definition: route.h:118
a2dCanvasObjectList * GetChildObjectList()
get the list where the child objects are stored in.
Definition: canobj.cpp:2551
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
int m_widthp1
width of the routing raster array + 1
Definition: route.h:352
unsigned int m_cost
minimum cost to reach this point
Definition: route.h:136
void AddBorderPoint(BorderQueue *queue, RoutePoint *current, int nextx, int nexty, int dir, int prevdir)
Add a new point on the route.
Definition: route.cpp:301
int m_heightp1
height of the routing raster array + 1
Definition: route.h:356
unsigned m_mincostindex
ring index of the current minimum cost (starting point or ring buffer )
Definition: route.h:220
int m_freememory
Number of free elements in memory allocation block.
Definition: route.h:228
a2dWirePolylineL is a polyline that adjusts itself when the objects it connects move ...
Definition: wire.h:42
RoutePoint & GetRoutePoint(int x, int y, int dir)
Get an element of the route point array.
Definition: route.h:274
unsigned char m_prevdir
direction of the previous point
Definition: route.h:158
used to change a property on objects
Definition: drawing.h:2244
bool GetValid() const
returns true if boundingbox is calculated properly and therefore its valid flag is set...
Definition: bbox.cpp:299
void Expand(const a2dPoint2D &, const a2dPoint2D &)
expand boundingbox width two points
Definition: bbox.cpp:155
double GetMinX() const
get minimum X of the boundingbox
Definition: bbox.cpp:304
#define forEachIn(listtype, list)
easy iteration for a2dlist
Definition: a2dlist.h:111
a2dCanvasObject * m_showobject
the show object given in the constructor
Definition: route.h:348
double GetPosX() const
get x position from affine matrix
Definition: canobj.h:527
void SetSegments(a2dVertexList *points)
Set the list of points ( the old list is NOT DELETED !!! )
Definition: polygon.cpp:830
#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
Normal straight line segment in a2dVertexList and a2dVertexArray.
Definition: polyver.h:163
~a2dRouteData()
Destructor.
Definition: route.cpp:289
Class for rerouting wires.
Definition: route.h:51
bool IsNotEmpty()
Check if the queue is empty.
Definition: route.h:192
bool IsInternal() const
see SetInternal()
Definition: canpin.h:447
Contains a2dDrawing Class to hold a drawing.
used to set the complete Segment list/array of polygons
Definition: drawing.h:2102
bool GetRerouteAdded() const
see SetRerouteAdded()
Definition: wire.h:80
unsigned char m_direction
direction to the source
Definition: route.h:156
virtual bool Submit(a2dCommand *command, bool storeIt=true)
next to the base class submit, it sets a2DocumentCommandProcessor for a2dCommand
Definition: comevt.cpp:842
Memory allocation block.
Definition: route.h:208
A 2x3 affine matrix class for 2D transformations.
Definition: afmatrix.h:53
double GetMaxX() const
get maximum X of the boundingbox
Definition: bbox.cpp:316
double GetPosY() const
get y position from affine matrix
Definition: canobj.h:530
int m_width
width of the routing raster array
Definition: route.h:350
unsigned char m_prevdir
direction of the previous point
Definition: route.h:142
static double m_raster
the size of the raster
Definition: route.h:358
BorderPoint * m_freelist
The starting point of the free list.
Definition: route.h:224
unsigned short & GetVerticalOccupation(int x, int y)
Get an element of the vertical occupation array.
Definition: route.h:242
double m_x
x endpoint of line
Definition: polyver.h:232
the data structure holding the per point information
Definition: route.h:133
void MapBbox(const a2dAffineMatrix &matrix)
Definition: bbox.cpp:445
a2dCommandProcessor * GetCommandProcessor() const
Returns a pointer to the command processor associated with this document.
Definition: drawing.h:549
void SetFlagRect(const a2dBoundingBox &bbox, RoutePointFlag flag)
Set a RoutePoint flag in a rectangle.
Definition: route.cpp:988
double m_y
y endpoint of line
Definition: polyver.h:235
number of usual direction values
Definition: route.h:122
wire classes for connecting objects.
unsigned short m_x
coordinates of this point (only set if reachable)
Definition: route.h:144
start point
Definition: route.h:115
double GetMaxY() const
get maximum Y of the boundingbox
Definition: bbox.cpp:322
void AddOccupationRect(const a2dBoundingBox &bbox, short incr)
add a bounding box to the occupied area
Definition: route.cpp:897
bool m_ok
if true, the raster is initialized
Definition: route.h:346
list for a2dCanvasObject
bool RerouteWire(a2dWirePolylineL *wire, a2dPin *dispin, a2dPin *startpin, bool startisbegin, bool final)
Reroute a wire.
Definition: route.cpp:367
unsigned char m_direction
direction to the source (only set if reachable)
Definition: route.h:140
RoutePointFlag
flags for RoutePoint
Definition: route.h:97
bool IsHorizontalOccupied(int x, int y)
Is an element of the horizontal occupation array.
Definition: route.h:266
The a2dBoundingBox class stores one a2dBoundingBox of a a2dCanvasObject.
Definition: bbox.h:39
bool Invert(void)
Invert matrix.
Definition: afmatrix.cpp:197
double m_rasterinv
the inverse size of the raster
Definition: route.h:360
void SetRerouteAdded(bool onOff)
indicated if the wire is added recently to be rerouted, used in routing algorithms of wire between ob...
Definition: wire.h:77
unsigned short * m_verticaloccupation
occupation counts for vertical edges ( a 2d array )
Definition: route.h:367
double GetMinY() const
get minimum Y of the boundingbox
Definition: bbox.cpp:310
void SetPosXyPoint(const a2dPoint2D &pos)
set position to x,y
Definition: canobj.h:547
~BorderQueue()
destructor
Definition: route.cpp:55
basetype GetPropertyValue(const a2dObject *obj) const
Get the property value in obj.
Definition: id.inl:325
unsigned short m_flags
various flags
Definition: route.h:138
int m_rasterminx
the limits of the raster area
Definition: route.h:362
int m_height
height of the routing raster array
Definition: route.h:354
a2dCanvasObject * GetParent() const
get parent object of the pin
Definition: canpin.h:295
a2dRouteData(a2dCanvasObject *showobject, bool final)
Standard constructor takes the show object under which is routed.
Definition: route.cpp:166
a2dBoundingBox CalculateRoutingBbox(a2dCanvasObject *object)
Calculates the routing relevant bounding box of an object.
Definition: route.cpp:1074
pins and handles
void DumpOccupation(FILE *file)
Dump the occupation arrays.
Definition: route.cpp:1096
unsigned int m_cost
minimum cost to reach this point
Definition: route.h:154
bool GetReroute() const
see SetReroute()
Definition: wire.h:74
bool IsVerticalOccupied(int x, int y)
Is an element of the vertical occupation array.
Definition: route.h:258
void SetFlagPolyline(const a2dVertexList *points, const a2dAffineMatrix &trns, RoutePointFlag flag)
Set a RoutePoint flag along a polyline.
Definition: route.cpp:1016
void RmvBest()
Remove the best border point.
Definition: route.cpp:119
max usual direction value
Definition: route.h:120
route.cpp Source File -- Sun Oct 12 2014 17:04:23 -- Sun Oct 12 2014 -- 1.8.5 -- wxArt2D -- . -- Main Page Reference Documentation