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