KiCad PCB EDA Suite
auto_place_footprints.cpp
Go to the documentation of this file.
1 
6 /*
7  * This program source code file is part of KiCad, a free EDA CAD application.
8  *
9  * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
10  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
11  * Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
12  *
13  * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors.
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, you may find one here:
27  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
28  * or you may search the http://www.gnu.org website for the version 2 license,
29  * or you may write to the Free Software Foundation, Inc.,
30  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
31  */
32 
33 #include <fctsys.h>
34 #include <class_drawpanel.h>
35 #include <confirm.h>
36 #include <pcbnew.h>
37 #include <wxPcbStruct.h>
38 #include <gr_basic.h>
39 #include <macros.h>
40 #include <msgpanel.h>
41 
42 #include <autorout.h>
43 #include <cell.h>
44 
45 #include <class_board.h>
46 #include <class_module.h>
47 #include <class_track.h>
48 #include <class_drawsegment.h>
49 #include <convert_to_biu.h>
50 #include <base_units.h>
51 #include <protos.h>
52 
53 
54 #define GAIN 16
55 #define KEEP_OUT_MARGIN 500
56 
57 
58 /* Penalty (cost) for CntRot90 and CntRot180:
59  * CntRot90 and CntRot180 are from 0 (rotation allowed) to 10 (rotation not allowed)
60  */
61 static const double OrientPenality[11] =
62 {
63  2.0, // CntRot = 0 rotation prohibited
64  1.9, // CntRot = 1
65  1.8, // CntRot = 2
66  1.7, // CntRot = 3
67  1.6, // CntRot = 4
68  1.5, // CntRot = 5
69  1.4, // CntRot = 5
70  1.3, // CntRot = 7
71  1.2, // CntRot = 8
72  1.1, // CntRot = 9
73  1.0 // CntRot = 10 rotation authorized, no penalty
74 };
75 
76 // Cell states.
77 #define OUT_OF_BOARD -2
78 #define OCCUPED_By_MODULE -1
79 #define FREE_CELL 0
80 
81 
82 static wxPoint CurrPosition; // Current position of the current module placement
83 double MinCout;
84 
85 
86 /* generates the Routing matrix, used to fing the best placement
87  * of a footprint.
88  * Allocate a "bitmap" which is an image of the real board
89  * the bitmap handles:
90  * - The free areas
91  * - penalties (cell not occupied, but near occupied areas)
92  * - cells occupied by footprints, board cutout ...
93  */
94 int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel );
95 
96 /* searches for the optimal position of aModule.
97  * return 1 if placement impossible or 0 if OK.
98  */
99 static int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame,
100  MODULE* aModule, wxDC* aDC );
101 
102 /*
103  * Function compute_Ratsnest_PlaceModule
104  * displays the module's ratsnest during displacement, and assess the "cost"
105  * of the position.
106  *
107  * The cost is the longest ratsnest distance with penalty for connections
108  * approaching 45 degrees.
109  */
110 static double compute_Ratsnest_PlaceModule( BOARD* aBrd );
111 
112 /* Place a footprint on the Routing matrix.
113  */
114 void genModuleOnRoutingMatrix( MODULE* Module );
115 /*
116  * Displays the Placement/Routing matrix on the screen
117  */
118 static void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC );
119 
120 static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide );
121 
122 static void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
123  int marge, int aKeepOut, LSET aLayerMask );
124 
125 static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC );
126 static int propagate();
127 
128 void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC )
129 {
130  MODULE* currModule = NULL;
131  wxPoint PosOK;
132  wxPoint memopos;
133  int error;
134  PCB_LAYER_ID lay_tmp_TOP, lay_tmp_BOTTOM;
135 
136  // Undo: init list
137  PICKED_ITEMS_LIST newList;
138 
139  newList.m_Status = UR_CHANGED;
140  ITEM_PICKER picker( NULL, UR_CHANGED );
141 
142  if( GetBoard()->m_Modules == NULL )
143  return;
144 
145  m_canvas->SetAbortRequest( false );
146 
147  switch( place_mode )
148  {
149  case PLACE_1_MODULE:
150  currModule = Module;
151 
152  if( currModule == NULL )
153  return;
154 
155  currModule->SetIsPlaced( false );
156  currModule->SetNeedsPlaced( false );
157  break;
158 
159  case PLACE_OUT_OF_BOARD:
160  break;
161 
162  case PLACE_ALL:
163 
164  if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) )
165  return;
166 
167  break;
168 
169  case PLACE_INCREMENTAL:
170 
171  if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) )
172  return;
173 
174  break;
175  }
176 
177  memopos = CurrPosition;
178  lay_tmp_BOTTOM = g_Route_Layer_BOTTOM;
179  lay_tmp_TOP = g_Route_Layer_TOP;
180 
182 
183  // Ensure Board.m_GridRouting has a reasonable value:
184  if( RoutingMatrix.m_GridRouting < Millimeter2iu( 0.25 ) )
185  RoutingMatrix.m_GridRouting = Millimeter2iu( 0.25 );
186 
187  // Compute module parameters used in auto place
189  return;
190 
191  int moduleCount = 0;
192  Module = GetBoard()->m_Modules;
193 
194  for( ; Module != NULL; Module = Module->Next() )
195  {
196  Module->SetNeedsPlaced( false );
197 
198  switch( place_mode )
199  {
200  case PLACE_1_MODULE:
201 
202  if( currModule == Module )
203  {
204  // Module will be placed, add to undo.
205  picker.SetItem( currModule );
206  newList.PushItem( picker );
207  Module->SetNeedsPlaced( true );
208  }
209 
210  break;
211 
212  case PLACE_OUT_OF_BOARD:
213  Module->SetIsPlaced( false );
214 
215  if( Module->IsLocked() )
216  break;
217 
218  if( !RoutingMatrix.m_BrdBox.Contains( Module->GetPosition() ) )
219  {
220  // Module will be placed, add to undo.
221  picker.SetItem( Module );
222  newList.PushItem( picker );
223  Module->SetNeedsPlaced( true );
224  }
225 
226  break;
227 
228  case PLACE_ALL:
229  Module->SetIsPlaced( false );
230 
231  if( Module->IsLocked() )
232  break;
233 
234  // Module will be placed, add to undo.
235  picker.SetItem( Module );
236  newList.PushItem( picker );
237  Module->SetNeedsPlaced( true );
238  break;
239 
240  case PLACE_INCREMENTAL:
241 
242  if( Module->IsLocked() )
243  {
244  Module->SetIsPlaced( false );
245  break;
246  }
247 
248  if( !Module->NeedsPlaced() )
249  {
250  // Module will be placed, add to undo.
251  picker.SetItem( Module );
252  newList.PushItem( picker );
253  Module->SetNeedsPlaced( true );
254  }
255 
256  break;
257  }
258 
259  if( Module->NeedsPlaced() ) // Erase from screen
260  {
261  moduleCount++;
262  Module->Draw( m_canvas, DC, GR_XOR );
263  }
264  else
265  {
266  genModuleOnRoutingMatrix( Module );
267  }
268  }
269 
270  // Undo command: prepare list
271  if( newList.GetCount() )
272  SaveCopyInUndoList( newList, UR_CHANGED );
273 
274  int cnt = 0;
275  wxString msg;
276 
277  while( ( Module = PickModule( this, DC ) ) != NULL )
278  {
279  // Display some info about activity, module placement can take a while:
280  msg.Printf( _( "Place footprint %d of %d" ), cnt, moduleCount );
281  SetStatusText( msg );
282 
283  double initialOrient = Module->GetOrientation();
284  // Display fill area of interest, barriers, penalties.
286 
287  error = getOptimalModulePlacement( this, Module, DC );
288  double bestScore = MinCout;
289  double bestRotation = 0.0;
290  int rotAllowed;
291  PosOK = CurrPosition;
292 
293  if( error == ESC )
294  goto end_of_tst;
295 
296  // Try orientations 90, 180, 270 degrees from initial orientation
297  rotAllowed = Module->GetPlacementCost180();
298 
299  if( rotAllowed != 0 )
300  {
301  Rotate_Module( DC, Module, 1800.0, true );
302  error = getOptimalModulePlacement( this, Module, DC );
303  MinCout *= OrientPenality[rotAllowed];
304 
305  if( bestScore > MinCout ) // This orientation is better.
306  {
307  PosOK = CurrPosition;
308  bestScore = MinCout;
309  bestRotation = 1800.0;
310  }
311  else
312  {
313  Rotate_Module( DC, Module, initialOrient, false );
314  }
315 
316  if( error == ESC )
317  goto end_of_tst;
318  }
319 
320  // Determine if the best orientation of a module is 90.
321  rotAllowed = Module->GetPlacementCost90();
322 
323  if( rotAllowed != 0 )
324  {
325  Rotate_Module( DC, Module, 900.0, true );
326  error = getOptimalModulePlacement( this, Module, DC );
327  MinCout *= OrientPenality[rotAllowed];
328 
329  if( bestScore > MinCout ) // This orientation is better.
330  {
331  PosOK = CurrPosition;
332  bestScore = MinCout;
333  bestRotation = 900.0;
334  }
335  else
336  {
337  Rotate_Module( DC, Module, initialOrient, false );
338  }
339 
340  if( error == ESC )
341  goto end_of_tst;
342  }
343 
344  // Determine if the best orientation of a module is -90.
345  if( rotAllowed != 0 )
346  {
347  Rotate_Module( DC, Module, 2700.0, true );
348  error = getOptimalModulePlacement( this, Module, DC );
349  MinCout *= OrientPenality[rotAllowed];
350 
351  if( bestScore > MinCout ) // This orientation is better.
352  {
353  PosOK = CurrPosition;
354  bestScore = MinCout;
355  bestRotation = 2700.0;
356  }
357  else
358  {
359  Rotate_Module( DC, Module, initialOrient, false );
360  }
361 
362  if( error == ESC )
363  goto end_of_tst;
364  }
365 
366 end_of_tst:
367 
368  if( error == ESC )
369  break;
370 
371  // Place module.
372  CurrPosition = GetCrossHairPosition();
373  SetCrossHairPosition( PosOK );
374 
375  PlaceModule( Module, DC );
376 
377  bestRotation += initialOrient;
378 
379  if( bestRotation != Module->GetOrientation() )
380  Rotate_Module( DC, Module, bestRotation, false );
381 
382  SetCrossHairPosition( CurrPosition );
383 
384  Module->CalculateBoundingBox();
385 
386  genModuleOnRoutingMatrix( Module );
387  Module->SetIsPlaced( true );
388  Module->SetNeedsPlaced( false );
389  }
390 
391  CurrPosition = memopos;
392 
394 
395  g_Route_Layer_TOP = lay_tmp_TOP;
396  g_Route_Layer_BOTTOM = lay_tmp_BOTTOM;
397 
398  Module = GetBoard()->m_Modules;
399 
400  for( ; Module != NULL; Module = Module->Next() )
401  {
402  Module->CalculateBoundingBox();
403  }
404 
405  GetBoard()->m_Status_Pcb = 0;
406  Compile_Ratsnest( DC, true );
407  m_canvas->ReDraw( DC, true );
408 }
409 
410 
411 void drawPlacementRoutingMatrix( BOARD* aBrd, wxDC* DC )
412 {
413  int ii, jj;
414  COLOR4D color;
415  int ox, oy;
416  MATRIX_CELL top_state, bottom_state;
417 
418  GRSetDrawMode( DC, GR_COPY );
419 
420  for( ii = 0; ii < RoutingMatrix.m_Nrows; ii++ )
421  {
423 
424  for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ )
425  {
427  color = COLOR4D::BLACK;
428 
429  top_state = RoutingMatrix.GetCell( ii, jj, TOP );
430  bottom_state = RoutingMatrix.GetCell( ii, jj, BOTTOM );
431 
432  if( top_state & CELL_is_ZONE )
433  color = COLOR4D( BLUE );
434 
435  // obstacles
436  if( ( top_state & CELL_is_EDGE ) || ( bottom_state & CELL_is_EDGE ) )
437  color = COLOR4D::WHITE;
438  else if( top_state & ( HOLE | CELL_is_MODULE ) )
439  color = COLOR4D( LIGHTRED );
440  else if( bottom_state & (HOLE | CELL_is_MODULE) )
441  color = COLOR4D( LIGHTGREEN );
442  else // Display the filling and keep out regions.
443  {
444  if( RoutingMatrix.GetDist( ii, jj, TOP )
445  || RoutingMatrix.GetDist( ii, jj, BOTTOM ) )
446  color = DARKGRAY;
447  }
448 
449  GRPutPixel( NULL, DC, ox, oy, color );
450  }
451  }
452 }
453 
454 
455 int genPlacementRoutingMatrix( BOARD* aBrd, EDA_MSG_PANEL* messagePanel )
456 {
457  wxString msg;
458 
460 
461  EDA_RECT bbox = aBrd->GetBoardEdgesBoundingBox();
462 
463  if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
464  {
465  DisplayError( NULL, _( "No PCB edge found, unknown board size!" ) );
466  return 0;
467  }
468 
469  RoutingMatrix.ComputeMatrixSize( aBrd, true );
470  int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows;
471 
472  messagePanel->EraseMsgBox();
473  msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols );
474  messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN );
475  msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows );
476  messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN );
477  msg.Printf( wxT( "%d" ), nbCells );
478  messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW );
479 
480  // Choose the number of board sides.
482 
484 
485  // Display memory usage.
486  msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 );
487  messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN );
488 
490 
493 
495 
496  // Place the edge layer segments
497  TRACK TmpSegm( NULL );
498 
499  TmpSegm.SetLayer( UNDEFINED_LAYER );
500  TmpSegm.SetNetCode( -1 );
501  TmpSegm.SetWidth( RoutingMatrix.m_GridRouting / 2 );
502 
503  for( auto PtStruct : aBrd->Drawings() )
504  {
505  DRAWSEGMENT* DrawSegm;
506 
507  switch( PtStruct->Type() )
508  {
509  case PCB_LINE_T:
510  DrawSegm = (DRAWSEGMENT*) PtStruct;
511 
512  if( DrawSegm->GetLayer() != Edge_Cuts )
513  break;
514 
515  TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
517  break;
518 
519  case PCB_TEXT_T:
520  default:
521  break;
522  }
523  }
524 
525  // Mark cells of the routing matrix to CELL_is_ZONE
526  // (i.e. availlable cell to place a module )
527  // Init a starting point of attachment to the area.
529  BOTTOM, CELL_is_ZONE );
530 
531  // find and mark all other availlable cells:
532  for( int ii = 1; ii != 0; )
533  ii = propagate();
534 
535  // Initialize top layer. to the same value as the bottom layer
538  nbCells * sizeof(MATRIX_CELL) );
539 
540  return 1;
541 }
542 
543 
544 /* Place module on Routing matrix.
545  */
547 {
548  int ox, oy, fx, fy;
549  LSET layerMask;
550  D_PAD* Pad;
551 
552  EDA_RECT fpBBox = Module->GetBoundingBox();
553 
554  fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 );
555  ox = fpBBox.GetX();
556  fx = fpBBox.GetRight();
557  oy = fpBBox.GetY();
558  fy = fpBBox.GetBottom();
559 
560  if( ox < RoutingMatrix.m_BrdBox.GetX() )
561  ox = RoutingMatrix.m_BrdBox.GetX();
562 
563  if( ox > RoutingMatrix.m_BrdBox.GetRight() )
565 
566  if( fx < RoutingMatrix.m_BrdBox.GetX() )
567  fx = RoutingMatrix.m_BrdBox.GetX();
568 
569  if( fx > RoutingMatrix.m_BrdBox.GetRight() )
571 
572  if( oy < RoutingMatrix.m_BrdBox.GetY() )
573  oy = RoutingMatrix.m_BrdBox.GetY();
574 
575  if( oy > RoutingMatrix.m_BrdBox.GetBottom() )
577 
578  if( fy < RoutingMatrix.m_BrdBox.GetY() )
579  fy = RoutingMatrix.m_BrdBox.GetY();
580 
581  if( fy > RoutingMatrix.m_BrdBox.GetBottom() )
583 
584  if( Module->GetLayer() == F_Cu )
585  layerMask.set( F_Cu );
586 
587  if( Module->GetLayer() == B_Cu )
588  layerMask.set( B_Cu );
589 
590  TraceFilledRectangle( ox, oy, fx, fy, layerMask,
592 
593  // Trace pads + clearance areas.
594  for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() )
595  {
596  int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance();
597  ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL );
598  }
599 
600  // Trace clearance.
601  int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN;
602  CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
603 }
604 
605 
606 // A minor helper function to draw a bounding box:
607 inline void draw_FootprintRect( EDA_RECT* aClipBox, wxDC* aDC, EDA_RECT& fpBBox, COLOR4D aColor )
608 {
609 #ifndef USE_WX_OVERLAY
610  GRRect( aClipBox, aDC, fpBBox, 0, aColor );
611 #endif
612 }
613 
614 
615 int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
616 {
617  int error = 1;
618  wxPoint LastPosOK;
619  double min_cost, curr_cost, Score;
620  bool TstOtherSide;
621  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aFrame->GetDisplayOptions();
622  BOARD* brd = aFrame->GetBoard();
623 
624  aModule->CalculateBoundingBox();
625 
626  bool showRats = displ_opts->m_Show_Module_Ratsnest;
627  displ_opts->m_Show_Module_Ratsnest = false;
628 
630  aFrame->SetMsgPanel( aModule );
631 
632  LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin();
633 
634  wxPoint mod_pos = aModule->GetPosition();
635  EDA_RECT fpBBox = aModule->GetFootprintRect();
636 
637  // Move fpBBox to have the footprint position at (0,0)
638  fpBBox.Move( -mod_pos );
639  wxPoint fpBBoxOrg = fpBBox.GetOrigin();
640 
641  // Calculate the limit of the footprint position, relative
642  // to the routing matrix area
643  wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
644 
645  wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
646 
647  // Stay on grid.
648  initialPos.x -= initialPos.x % RoutingMatrix.m_GridRouting;
649  initialPos.y -= initialPos.y % RoutingMatrix.m_GridRouting;
650 
651  CurrPosition = initialPos;
652 
653  // Undraw the current footprint
654  aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) );
655 
656  g_Offset_Module = mod_pos - CurrPosition;
657 
658  /* Examine pads, and set TstOtherSide to true if a footprint
659  * has at least 1 pad through.
660  */
661  TstOtherSide = false;
662 
664  {
665  LSET other( aModule->GetLayer() == B_Cu ? F_Cu : B_Cu );
666 
667  for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
668  {
669  if( !( pad->GetLayerSet() & other ).any() )
670  continue;
671 
672  TstOtherSide = true;
673  break;
674  }
675  }
676 
677  // Draw the initial bounding box position
678  COLOR4D color = COLOR4D( BROWN );
679  fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
680  draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
681 
682  min_cost = -1.0;
683  aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
684 
685  for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting )
686  {
687  wxYield();
688 
689  if( aFrame->GetCanvas()->GetAbortRequest() )
690  {
691  if( IsOK( aFrame, _( "OK to abort?" ) ) )
692  {
693  displ_opts->m_Show_Module_Ratsnest = showRats;
694  return ESC;
695  }
696  else
697  aFrame->GetCanvas()->SetAbortRequest( false );
698  }
699 
700  CurrPosition.y = initialPos.y;
701 
702  for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
703  {
704  // Erase traces.
705  draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
706 
707  fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
708  g_Offset_Module = mod_pos - CurrPosition;
709  int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
710 
711  // Draw at new place
712  color = keepOutCost >= 0 ? BROWN : RED;
713  draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
714 
715  if( keepOutCost >= 0 ) // i.e. if the module can be put here
716  {
717  error = 0;
718  aFrame->build_ratsnest_module( aModule );
719  curr_cost = compute_Ratsnest_PlaceModule( brd );
720  Score = curr_cost + keepOutCost;
721 
722  if( (min_cost >= Score ) || (min_cost < 0 ) )
723  {
724  LastPosOK = CurrPosition;
725  min_cost = Score;
726  wxString msg;
727  msg.Printf( wxT( "Score %g, pos %s, %s" ),
728  min_cost,
729  GetChars( ::CoordinateToString( LastPosOK.x ) ),
730  GetChars( ::CoordinateToString( LastPosOK.y ) ) );
731  aFrame->SetStatusText( msg );
732  }
733  }
734  }
735  }
736 
737  // erasing the last traces
738  GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
739 
740  displ_opts->m_Show_Module_Ratsnest = showRats;
741 
742  // Regeneration of the modified variable.
743  CurrPosition = LastPosOK;
744 
745  brd->m_Status_Pcb &= ~( RATSNEST_ITEM_LOCAL_OK | LISTE_PAD_OK );
746 
747  MinCout = min_cost;
748  return error;
749 }
750 
751 
752 /* Test if the rectangular area (ux, ux .. y0, y1):
753  * - is a free zone (except OCCUPED_By_MODULE returns)
754  * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
755  *
756  * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
757  */
758 int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
759 {
760  EDA_RECT rect = aRect;
761 
762  rect.Inflate( RoutingMatrix.m_GridRouting / 2 );
763 
764  wxPoint start = rect.GetOrigin();
765  wxPoint end = rect.GetEnd();
766 
767  start -= RoutingMatrix.m_BrdBox.GetOrigin();
769 
770  int row_min = start.y / RoutingMatrix.m_GridRouting;
771  int row_max = end.y / RoutingMatrix.m_GridRouting;
772  int col_min = start.x / RoutingMatrix.m_GridRouting;
773  int col_max = end.x / RoutingMatrix.m_GridRouting;
774 
775  if( start.y > row_min * RoutingMatrix.m_GridRouting )
776  row_min++;
777 
778  if( start.x > col_min * RoutingMatrix.m_GridRouting )
779  col_min++;
780 
781  if( row_min < 0 )
782  row_min = 0;
783 
784  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
785  row_max = RoutingMatrix.m_Nrows - 1;
786 
787  if( col_min < 0 )
788  col_min = 0;
789 
790  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
791  col_max = RoutingMatrix.m_Ncols - 1;
792 
793  for( int row = row_min; row <= row_max; row++ )
794  {
795  for( int col = col_min; col <= col_max; col++ )
796  {
797  unsigned int data = RoutingMatrix.GetCell( row, col, side );
798 
799  if( ( data & CELL_is_ZONE ) == 0 )
800  return OUT_OF_BOARD;
801 
802  if( (data & CELL_is_MODULE) )
803  return OCCUPED_By_MODULE;
804  }
805  }
806 
807  return FREE_CELL;
808 }
809 
810 
811 /* Calculates and returns the clearance area of the rectangular surface
812  * aRect):
813  * (Sum of cells in terms of distance)
814  */
815 unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side )
816 {
817  wxPoint start = aRect.GetOrigin();
818  wxPoint end = aRect.GetEnd();
819 
820  start -= RoutingMatrix.m_BrdBox.GetOrigin();
822 
823  int row_min = start.y / RoutingMatrix.m_GridRouting;
824  int row_max = end.y / RoutingMatrix.m_GridRouting;
825  int col_min = start.x / RoutingMatrix.m_GridRouting;
826  int col_max = end.x / RoutingMatrix.m_GridRouting;
827 
828  if( start.y > row_min * RoutingMatrix.m_GridRouting )
829  row_min++;
830 
831  if( start.x > col_min * RoutingMatrix.m_GridRouting )
832  col_min++;
833 
834  if( row_min < 0 )
835  row_min = 0;
836 
837  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
838  row_max = RoutingMatrix.m_Nrows - 1;
839 
840  if( col_min < 0 )
841  col_min = 0;
842 
843  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
844  col_max = RoutingMatrix.m_Ncols - 1;
845 
846  unsigned int keepOutCost = 0;
847 
848  for( int row = row_min; row <= row_max; row++ )
849  {
850  for( int col = col_min; col <= col_max; col++ )
851  {
852  // RoutingMatrix.GetDist returns the "cost" of the cell
853  // at position (row, col)
854  // in autoplace this is the cost of the cell, if it is
855  // inside aRect
856  keepOutCost += RoutingMatrix.GetDist( row, col, side );
857  }
858  }
859 
860  return keepOutCost;
861 }
862 
863 
864 /* Test if the module can be placed on the board.
865  * Returns the value TstRectangle().
866  * Module is known by its bounding box
867  */
868 int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
869 {
870  int side = TOP;
871  int otherside = BOTTOM;
872 
873  if( aModule->GetLayer() == B_Cu )
874  {
875  side = BOTTOM; otherside = TOP;
876  }
877 
878  EDA_RECT fpBBox = aModule->GetFootprintRect();
879  fpBBox.Move( -g_Offset_Module );
880 
881  int diag = TstRectangle( Pcb, fpBBox, side );
882 
883  if( diag != FREE_CELL )
884  return diag;
885 
886  if( TstOtherSide )
887  {
888  diag = TstRectangle( Pcb, fpBBox, otherside );
889 
890  if( diag != FREE_CELL )
891  return diag;
892  }
893 
894  int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN;
895 
896  fpBBox.Inflate( marge );
897  return CalculateKeepOutArea( fpBBox, side );
898 }
899 
900 
902 {
903  double curr_cost;
904  wxPoint start; // start point of a ratsnest
905  wxPoint end; // end point of a ratsnest
906  int dx, dy;
907 
908  if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 )
909  return -1;
910 
911  curr_cost = 0;
912 
913  for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ )
914  {
915  RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii];
916 
917  if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) )
918  continue; // Skip ratsnest between 2 pads of the current module
919 
920  // Skip modules not inside the board area
921  MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent();
922 
923  if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) )
924  continue;
925 
926  start = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module;
927  end = pt_local_rats_nest->m_PadEnd->GetPosition();
928 
929  // Cost of the ratsnest.
930  dx = end.x - start.x;
931  dy = end.y - start.y;
932 
933  dx = abs( dx );
934  dy = abs( dy );
935 
936  // ttry to have always dx >= dy to calculate the cost of the rastsnet
937  if( dx < dy )
938  std::swap( dx, dy );
939 
940  // Cost of the connection = length + penalty due to the slope
941  // dx is the biggest length relative to the X or Y axis
942  // the penalty is max for 45 degrees ratsnests,
943  // and 0 for horizontal or vertical ratsnests.
944  // For Horizontal and Vertical ratsnests, dy = 0;
945  double conn_cost = hypot( dx, dy * 2.0 );
946  curr_cost += conn_cost; // Total cost = sum of costs of each connection
947  }
948 
949  return curr_cost;
950 }
951 
952 
963 void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
964  int marge, int aKeepOut, LSET aLayerMask )
965 {
966  int row, col;
967  int row_min, row_max, col_min, col_max, pmarge;
968  int trace = 0;
969  DIST_CELL data, LocalKeepOut;
970  int lgain, cgain;
971 
972  if( aLayerMask[g_Route_Layer_BOTTOM] )
973  trace = 1; // Trace on bottom layer.
974 
976  trace |= 2; // Trace on top layer.
977 
978  if( trace == 0 )
979  return;
980 
981  ux0 -= RoutingMatrix.m_BrdBox.GetX();
982  uy0 -= RoutingMatrix.m_BrdBox.GetY();
983  ux1 -= RoutingMatrix.m_BrdBox.GetX();
984  uy1 -= RoutingMatrix.m_BrdBox.GetY();
985 
986  ux0 -= marge; ux1 += marge;
987  uy0 -= marge; uy1 += marge;
988 
989  pmarge = marge / RoutingMatrix.m_GridRouting;
990 
991  if( pmarge < 1 )
992  pmarge = 1;
993 
994  // Calculate the coordinate limits of the rectangle.
995  row_max = uy1 / RoutingMatrix.m_GridRouting;
996  col_max = ux1 / RoutingMatrix.m_GridRouting;
997  row_min = uy0 / RoutingMatrix.m_GridRouting;
998 
999  if( uy0 > row_min * RoutingMatrix.m_GridRouting )
1000  row_min++;
1001 
1002  col_min = ux0 / RoutingMatrix.m_GridRouting;
1003 
1004  if( ux0 > col_min * RoutingMatrix.m_GridRouting )
1005  col_min++;
1006 
1007  if( row_min < 0 )
1008  row_min = 0;
1009 
1010  if( row_max >= (RoutingMatrix.m_Nrows - 1) )
1011  row_max = RoutingMatrix.m_Nrows - 1;
1012 
1013  if( col_min < 0 )
1014  col_min = 0;
1015 
1016  if( col_max >= (RoutingMatrix.m_Ncols - 1) )
1017  col_max = RoutingMatrix.m_Ncols - 1;
1018 
1019  for( row = row_min; row <= row_max; row++ )
1020  {
1021  lgain = 256;
1022 
1023  if( row < pmarge )
1024  lgain = ( 256 * row ) / pmarge;
1025  else if( row > row_max - pmarge )
1026  lgain = ( 256 * ( row_max - row ) ) / pmarge;
1027 
1028  for( col = col_min; col <= col_max; col++ )
1029  {
1030  // RoutingMatrix Dist map containt the "cost" of the cell
1031  // at position (row, col)
1032  // in autoplace this is the cost of the cell, when
1033  // a footprint overlaps it, near a "master" footprint
1034  // this cost is hight near the "master" footprint
1035  // and decrease with the distance
1036  cgain = 256;
1037  LocalKeepOut = aKeepOut;
1038 
1039  if( col < pmarge )
1040  cgain = ( 256 * col ) / pmarge;
1041  else if( col > col_max - pmarge )
1042  cgain = ( 256 * ( col_max - col ) ) / pmarge;
1043 
1044  cgain = ( cgain * lgain ) / 256;
1045 
1046  if( cgain != 256 )
1047  LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
1048 
1049  if( trace & 1 )
1050  {
1051  data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
1052  RoutingMatrix.SetDist( row, col, BOTTOM, data );
1053  }
1054 
1055  if( trace & 2 )
1056  {
1057  data = RoutingMatrix.GetDist( row, col, TOP );
1058  data = std::max( data, LocalKeepOut );
1059  RoutingMatrix.SetDist( row, col, TOP, data );
1060  }
1061  }
1062  }
1063 }
1064 
1065 
1066 // Sort routines
1067 static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
1068 {
1069  double ff1, ff2;
1070 
1071  ff1 = ref->GetArea() * ref->GetPadCount();
1072  ff2 = compare->GetArea() * compare->GetPadCount();
1073 
1074  return ff2 < ff1;
1075 }
1076 
1077 
1078 static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
1079 {
1080  double ff1, ff2;
1081 
1082  ff1 = ref->GetArea() * ref->GetFlag();
1083  ff2 = compare->GetArea() * compare->GetFlag();
1084  return ff2 < ff1;
1085 }
1086 
1087 
1095 static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
1096 {
1097  MODULE* Module;
1098  std::vector <MODULE*> moduleList;
1099 
1100  // Build sorted footprints list (sort by decreasing size )
1101  Module = pcbframe->GetBoard()->m_Modules;
1102 
1103  for( ; Module != NULL; Module = Module->Next() )
1104  {
1105  Module->CalculateBoundingBox();
1106  moduleList.push_back( Module );
1107  }
1108 
1109  sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules );
1110 
1111  for( unsigned kk = 0; kk < moduleList.size(); kk++ )
1112  {
1113  Module = moduleList[kk];
1114  Module->SetFlag( 0 );
1115 
1116  if( !Module->NeedsPlaced() )
1117  continue;
1118 
1119  pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
1120  pcbframe->SetMsgPanel( Module );
1121  pcbframe->build_ratsnest_module( Module );
1122 
1123  // Calculate external ratsnest.
1124  for( unsigned ii = 0; ii < pcbframe->GetBoard()->m_LocalRatsnest.size(); ii++ )
1125  {
1126  if( ( pcbframe->GetBoard()->m_LocalRatsnest[ii].m_Status &
1127  LOCAL_RATSNEST_ITEM ) == 0 )
1128  Module->IncrementFlag();
1129  }
1130  }
1131 
1132  pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
1133 
1134  sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
1135 
1136  // Search for "best" module.
1137  MODULE* bestModule = NULL;
1138  MODULE* altModule = NULL;
1139 
1140  for( unsigned ii = 0; ii < moduleList.size(); ii++ )
1141  {
1142  Module = moduleList[ii];
1143 
1144  if( !Module->NeedsPlaced() )
1145  continue;
1146 
1147  altModule = Module;
1148 
1149  if( Module->GetFlag() == 0 )
1150  continue;
1151 
1152  bestModule = Module;
1153  break;
1154  }
1155 
1156  if( bestModule )
1157  return bestModule;
1158  else
1159  return altModule;
1160 }
1161 
1162 
1188 {
1189  int row, col;
1190  long current_cell, old_cell_H;
1191  std::vector<long> pt_cell_V;
1192  int nbpoints = 0;
1193 
1194 #define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
1195 
1196  pt_cell_V.reserve( std::max( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) );
1197  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1198 
1199  // Search from left to right and top to bottom.
1200  for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
1201  {
1202  old_cell_H = 0;
1203 
1204  for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
1205  {
1206  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1207 
1208  if( current_cell == 0 ) // a free cell is found
1209  {
1210  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
1211  {
1212  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1213  current_cell = CELL_is_ZONE;
1214  nbpoints++;
1215  }
1216  }
1217 
1218  pt_cell_V[col] = old_cell_H = current_cell;
1219  }
1220  }
1221 
1222  // Search from right to left and top to bottom/
1223  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1224 
1225  for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
1226  {
1227  old_cell_H = 0;
1228 
1229  for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
1230  {
1231  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1232 
1233  if( current_cell == 0 ) // a free cell is found
1234  {
1235  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
1236  {
1237  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1238  current_cell = CELL_is_ZONE;
1239  nbpoints++;
1240  }
1241  }
1242 
1243  pt_cell_V[col] = old_cell_H = current_cell;
1244  }
1245  }
1246 
1247  // Search from bottom to top and right to left.
1248  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1249 
1250  for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
1251  {
1252  old_cell_H = 0;
1253 
1254  for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
1255  {
1256  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1257 
1258  if( current_cell == 0 ) // a free cell is found
1259  {
1260  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
1261  {
1262  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1263  current_cell = CELL_is_ZONE;
1264  nbpoints++;
1265  }
1266  }
1267 
1268  pt_cell_V[row] = old_cell_H = current_cell;
1269  }
1270  }
1271 
1272  // Search from bottom to top and left to right.
1273  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1274 
1275  for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
1276  {
1277  old_cell_H = 0;
1278 
1279  for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
1280  {
1281  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1282 
1283  if( current_cell == 0 ) // a free cell is found
1284  {
1285  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
1286  {
1287  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1288  current_cell = CELL_is_ZONE;
1289  nbpoints++;
1290  }
1291  }
1292 
1293  pt_cell_V[row] = old_cell_H = current_cell;
1294  }
1295  }
1296 
1297  return nbpoints;
1298 }
int GetFlag() const
Definition: class_module.h:202
Definition: colors.h:57
wxString CoordinateToString(int aValue, bool aConvertToMils)
Function CoordinateToString is a helper to convert the integer coordinate aValue to a string in inche...
Definition: base_units.cpp:117
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, LSET side, int color, int op_logic)
Definition: graphpcb.cpp:478
BOARD_ITEM_CONTAINER * GetParent() const
static wxPoint CurrPosition
wxPoint g_Offset_Module
Definition: pcbnew.cpp:73
PCB_LAYER_ID g_Route_Layer_TOP
Definition: pcbnew.cpp:68
PCB_LAYER_ID g_Route_Layer_BOTTOM
Definition: pcbnew.cpp:69
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
int InitRoutingMatrix()
Function InitBoard initializes the data structures.
static int getOptimalModulePlacement(PCB_EDIT_FRAME *aFrame, MODULE *aModule, wxDC *aDC)
void IncrementFlag()
Definition: class_module.h:201
long trace
Definition: solve.cpp:232
void AutoPlaceModule(MODULE *Module, int place_mode, wxDC *DC)
Function AutoPlaceModule automatically places footprints within the confines of the PCB edges...
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:290
static int propagate()
Function propagate Used only in autoplace calculations Uses the routing matrix to fill the cells with...
int genPlacementRoutingMatrix(BOARD *aBrd, EDA_MSG_PANEL *messagePanel)
static int TstModuleOnBoard(BOARD *Pcb, MODULE *Module, bool TstOtherSide)
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
Implementation of conversion functions that require both schematic and board internal units...
This file is part of the common library.
EDA_DRAW_PANEL * GetCanvas()
Definition: draw_frame.h:304
static const double OrientPenality[11]
double MinCout
static void drawPlacementRoutingMatrix(BOARD *aBrd, wxDC *DC)
bool Contains(const wxPoint &aPoint) const
Function Contains.
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, GR_DRAWMODE aDrawMode, const wxPoint &aOffset=ZeroOffset) override
Function Draw draws the footprint to the aDC.
#define CELL_is_EDGE
Definition: cell.h:42
Class BOARD to handle a board.
const wxPoint & GetPosition() const override
Definition: class_module.h:155
static bool sortFootprintsByRatsnestSize(MODULE *ref, MODULE *compare)
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
MODULE * Next() const
Definition: class_module.h:100
void build_ratsnest_module(MODULE *aModule, wxPoint aMoveVector)
Function build_ratsnest_module Build a ratsnest relative to one footprint.
Definition: ratsnest.cpp:184
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:140
void SetNeedsPlaced(bool needsPlaced)
Definition: class_module.h:264
int GetHeight() const
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
void SetOrigin(const wxPoint &pos)
BOARD * GetBoard() const
void Rotate_Module(wxDC *DC, MODULE *module, double angle, bool incremental)
Definition: modules.cpp:433
void PushItem(const ITEM_PICKER &aItem)
Function PushItem pushes aItem to the top of the list.
unsigned int CalculateKeepOutArea(const EDA_RECT &aRect, int side)
#define WRITE_CELL
Definition: autorout.h:190
bool NeedsPlaced() const
Definition: class_module.h:263
static MODULE * PickModule(PCB_EDIT_FRAME *pcbframe, wxDC *DC)
Function PickModule find the "best" module place The criteria are:
int GetPlacementCost90() const
Definition: class_module.h:533
class EDA_MSG_PANEL is a panel to display various information messages.
Definition: msgpanel.h:111
#define OCCUPED_By_MODULE
#define abs(a)
Definition: auxiliary.h:84
Functions relatives to tracks, vias and segments used to fill zones.
#define ESC
Definition: common.h:87
void * GetDisplayOptions() override
Function GetDisplayOptions returns the display options current in use Display options are relative to...
This file contains miscellaneous commonly used macros and functions.
void SetWidth(int aWidth)
Definition: class_track.h:114
void PlaceModule(MODULE *aModule, wxDC *aDC, bool aDoNotRecreateRatsnest=false)
Function PlaceModule places aModule at the current cursor position and updates module coordinates wit...
Definition: modules.cpp:352
#define TOP
Definition: autorout.h:49
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:797
const wxPoint & GetOrigin() const
#define OUT_OF_BOARD
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1077
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
#define LOCAL_RATSNEST_ITEM
Definition: class_netinfo.h:61
static double compute_Ratsnest_PlaceModule(BOARD *aBrd)
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:773
MATRIX_CELL * m_BoardSide[MAX_ROUTING_LAYERS_COUNT]
Definition: autorout.h:107
double GetOrientation() const
Definition: class_module.h:160
EDA_MSG_PANEL * m_messagePanel
Panel used to display information at the bottom of the main window.
Definition: draw_frame.h:128
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text...
#define NO_CELL_ZONE
Definition: colors.h:59
DIST_CELL GetDist(int aRow, int aCol, int aSide)
D_PAD * Next() const
Definition: class_pad.h:145
EDA_RECT * GetClipBox()
bool SetNetCode(int aNetCode, bool aNoAssert=false)
Function SetNetCode sets net using a net code.
Definition: colors.h:60
unsigned char MATRIX_CELL
Definition: autorout.h:81
void SetIsPlaced(bool isPlaced)
Definition: class_module.h:255
int GetBottom() const
void EraseMsgBox()
Definition: msgpanel.cpp:215
Class PICKED_ITEMS_LIST is a holder to handle information on schematic or board items.
static void CreateKeepOutRectangle(int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask)
Function CreateKeepOutRectangle builds the cost map: Cells ( in Dist map ) inside the rect x0...
void SaveCopyInUndoList(BOARD_ITEM *aItemToCopy, UNDO_REDO_T aTypeCommand, const wxPoint &aTransformPoint=wxPoint(0, 0)) override
Function SaveCopyInUndoList Creates a new entry in undo list of commands.
Definition: undo_redo.cpp:172
int GetRight() const
void SetItem(EDA_ITEM *aItem)
void SetMessage(int aXPosition, const wxString &aUpperText, const wxString &aLowerText, COLOR4D aColor)
Function SetMessage sets a message at aXPosition to aUpperText and aLowerText in the message panel...
Definition: msgpanel.cpp:145
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:236
void SetAbortRequest(bool aAbortRequest)
const wxPoint GetEnd() const
void Compile_Ratsnest(wxDC *aDC, bool aDisplayStatus)
Function Compile_Ratsnest Create the entire board ratsnest.
Definition: ratsnest.cpp:56
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
Class DISPLAY_OPTIONS handles display options like enable/disable some optional drawings.
Definition: pcbstruct.h:62
unsigned GetCount() const
Function GetCount.
void GRPutPixel(EDA_RECT *ClipBox, wxDC *DC, int x, int y, COLOR4D Color)
Definition: gr_basic.cpp:339
MATRIX_ROUTING_HEAD RoutingMatrix
Definition: autorout.cpp:51
EDA_DRAW_PANEL * m_canvas
The area to draw on.
Definition: draw_frame.h:92
bool ComputeMatrixSize(BOARD *aPcb, bool aUseBoardEdgesOnly=false)
Function ComputeMatrixSize calculates the number of rows and columns of dimensions of aPcb for routin...
bool GetAbortRequest() const
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
static bool Tri_PlaceModules(MODULE *ref, MODULE *compare)
void OrCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Definition: colors.h:58
int TstRectangle(BOARD *Pcb, const EDA_RECT &aRect, int side)
void SetDist(int aRow, int aCol, int aSide, DIST_CELL)
void ReDraw(wxDC *aDC, bool aEraseBackground=true)
Definition: draw_panel.cpp:607
#define GAIN
Class to handle a graphic segment.
double GetArea() const
Definition: class_module.h:525
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
DLIST< MODULE > m_Modules
Definition: class_board.h:245
#define CELL_is_MODULE
Definition: cell.h:41
void draw_FootprintRect(EDA_RECT *aClipBox, wxDC *aDC, EDA_RECT &fpBBox, COLOR4D aColor)
const wxRealPoint & GetGridSize() const
Return the grid size of the currently selected grid.
Class EDA_RECT handles the component boundary box.
int GetX() const
int GetWidth() const
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:546
PCB_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
Definition: colors.h:49
int GetY() const
void PlacePad(D_PAD *pt_pad, int type, int marge, int op_logic)
Definition: graphpcb.cpp:87
#define BOTTOM
Definition: autorout.h:50
void TraceSegmentPcb(TRACK *pt_segm, int type, int marge, int op_logic)
Definition: graphpcb.cpp:290
void DrawOutlinesWhenMoving(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aMoveVector)
Function DrawOutlinesWhenMoving draws in XOR mode the footprint when moving it to the aDC...
Definition: ratsnest.cpp:217
Module description (excepted pads)
Definition: colors.h:45
bool m_Show_Module_Ratsnest
Definition: pcbstruct.h:87
void SetCrossHairPosition(const wxPoint &aPosition, bool aSnapToGrid=true)
Function SetCrossHairPosition sets the screen cross hair position to aPosition in logical (drawing) u...
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
Message panel definition file.
EDA_RECT m_BrdBox
Definition: autorout.h:115
#define KEEP_OUT_MARGIN
Definition: colors.h:68
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:71
wxPoint GetCrossHairPosition(bool aInvertY=false) const
Function GetCrossHairPosition return the current cross hair position in logical (drawing) coordinates...
void genModuleOnRoutingMatrix(MODULE *Module)
int GetPlacementCost180() const
Definition: class_module.h:530
#define HOLE
Definition: cell.h:40
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:129
void SetFlag(int aFlag)
Definition: class_module.h:200
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
#define CELL_is_ZONE
Definition: cell.h:44
int m_Status_Pcb
Flags used in ratsnest calculation and update.
Definition: class_board.h:237
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
#define WRITE_OR_CELL
Definition: autorout.h:191
#define FREE_CELL
Definition: colors.h:62
int DIST_CELL
Definition: autorout.h:82