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  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  EDA_ITEM* PtStruct = aBrd->m_Drawings;
505 
506  for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
507  {
508  DRAWSEGMENT* DrawSegm;
509 
510  switch( PtStruct->Type() )
511  {
512  case PCB_LINE_T:
513  DrawSegm = (DRAWSEGMENT*) PtStruct;
514 
515  if( DrawSegm->GetLayer() != Edge_Cuts )
516  break;
517 
518  TraceSegmentPcb( DrawSegm, HOLE | CELL_is_EDGE,
520  break;
521 
522  case PCB_TEXT_T:
523  default:
524  break;
525  }
526  }
527 
528  // Mark cells of the routing matrix to CELL_is_ZONE
529  // (i.e. availlable cell to place a module )
530  // Init a starting point of attachment to the area.
532  BOTTOM, CELL_is_ZONE );
533 
534  // find and mark all other availlable cells:
535  for( int ii = 1; ii != 0; )
536  ii = propagate();
537 
538  // Initialize top layer. to the same value as the bottom layer
541  nbCells * sizeof(MATRIX_CELL) );
542 
543  return 1;
544 }
545 
546 
547 /* Place module on Routing matrix.
548  */
550 {
551  int ox, oy, fx, fy;
552  LSET layerMask;
553  D_PAD* Pad;
554 
555  EDA_RECT fpBBox = Module->GetBoundingBox();
556 
557  fpBBox.Inflate( RoutingMatrix.m_GridRouting / 2 );
558  ox = fpBBox.GetX();
559  fx = fpBBox.GetRight();
560  oy = fpBBox.GetY();
561  fy = fpBBox.GetBottom();
562 
563  if( ox < RoutingMatrix.m_BrdBox.GetX() )
564  ox = RoutingMatrix.m_BrdBox.GetX();
565 
566  if( ox > RoutingMatrix.m_BrdBox.GetRight() )
568 
569  if( fx < RoutingMatrix.m_BrdBox.GetX() )
570  fx = RoutingMatrix.m_BrdBox.GetX();
571 
572  if( fx > RoutingMatrix.m_BrdBox.GetRight() )
574 
575  if( oy < RoutingMatrix.m_BrdBox.GetY() )
576  oy = RoutingMatrix.m_BrdBox.GetY();
577 
578  if( oy > RoutingMatrix.m_BrdBox.GetBottom() )
580 
581  if( fy < RoutingMatrix.m_BrdBox.GetY() )
582  fy = RoutingMatrix.m_BrdBox.GetY();
583 
584  if( fy > RoutingMatrix.m_BrdBox.GetBottom() )
586 
587  if( Module->GetLayer() == F_Cu )
588  layerMask.set( F_Cu );
589 
590  if( Module->GetLayer() == B_Cu )
591  layerMask.set( B_Cu );
592 
593  TraceFilledRectangle( ox, oy, fx, fy, layerMask,
595 
596  // Trace pads + clearance areas.
597  for( Pad = Module->Pads(); Pad != NULL; Pad = Pad->Next() )
598  {
599  int margin = (RoutingMatrix.m_GridRouting / 2) + Pad->GetClearance();
600  ::PlacePad( Pad, CELL_is_MODULE, margin, WRITE_OR_CELL );
601  }
602 
603  // Trace clearance.
604  int margin = ( RoutingMatrix.m_GridRouting * Module->GetPadCount() ) / GAIN;
605  CreateKeepOutRectangle( ox, oy, fx, fy, margin, KEEP_OUT_MARGIN, layerMask );
606 }
607 
608 
609 // A minor helper function to draw a bounding box:
610 inline void draw_FootprintRect( EDA_RECT* aClipBox, wxDC* aDC, EDA_RECT& fpBBox, COLOR4D aColor )
611 {
612 #ifndef USE_WX_OVERLAY
613  GRRect( aClipBox, aDC, fpBBox, 0, aColor );
614 #endif
615 }
616 
617 
618 int getOptimalModulePlacement( PCB_EDIT_FRAME* aFrame, MODULE* aModule, wxDC* aDC )
619 {
620  int error = 1;
621  wxPoint LastPosOK;
622  double min_cost, curr_cost, Score;
623  bool TstOtherSide;
624  DISPLAY_OPTIONS* displ_opts = (DISPLAY_OPTIONS*)aFrame->GetDisplayOptions();
625  BOARD* brd = aFrame->GetBoard();
626 
627  aModule->CalculateBoundingBox();
628 
629  bool showRats = displ_opts->m_Show_Module_Ratsnest;
630  displ_opts->m_Show_Module_Ratsnest = false;
631 
633  aFrame->SetMsgPanel( aModule );
634 
635  LastPosOK = RoutingMatrix.m_BrdBox.GetOrigin();
636 
637  wxPoint mod_pos = aModule->GetPosition();
638  EDA_RECT fpBBox = aModule->GetFootprintRect();
639 
640  // Move fpBBox to have the footprint position at (0,0)
641  fpBBox.Move( -mod_pos );
642  wxPoint fpBBoxOrg = fpBBox.GetOrigin();
643 
644  // Calculate the limit of the footprint position, relative
645  // to the routing matrix area
646  wxPoint xylimit = RoutingMatrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
647 
648  wxPoint initialPos = RoutingMatrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
649 
650  // Stay on grid.
651  initialPos.x -= initialPos.x % RoutingMatrix.m_GridRouting;
652  initialPos.y -= initialPos.y % RoutingMatrix.m_GridRouting;
653 
654  CurrPosition = initialPos;
655 
656  // Undraw the current footprint
657  aModule->DrawOutlinesWhenMoving( aFrame->GetCanvas(), aDC, wxPoint( 0, 0 ) );
658 
659  g_Offset_Module = mod_pos - CurrPosition;
660 
661  /* Examine pads, and set TstOtherSide to true if a footprint
662  * has at least 1 pad through.
663  */
664  TstOtherSide = false;
665 
667  {
668  LSET other( aModule->GetLayer() == B_Cu ? F_Cu : B_Cu );
669 
670  for( D_PAD* pad = aModule->Pads(); pad; pad = pad->Next() )
671  {
672  if( !( pad->GetLayerSet() & other ).any() )
673  continue;
674 
675  TstOtherSide = true;
676  break;
677  }
678  }
679 
680  // Draw the initial bounding box position
681  COLOR4D color = COLOR4D( BROWN );
682  fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
683  draw_FootprintRect(aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color);
684 
685  min_cost = -1.0;
686  aFrame->SetStatusText( wxT( "Score ??, pos ??" ) );
687 
688  for( ; CurrPosition.x < xylimit.x; CurrPosition.x += RoutingMatrix.m_GridRouting )
689  {
690  wxYield();
691 
692  if( aFrame->GetCanvas()->GetAbortRequest() )
693  {
694  if( IsOK( aFrame, _( "OK to abort?" ) ) )
695  {
696  displ_opts->m_Show_Module_Ratsnest = showRats;
697  return ESC;
698  }
699  else
700  aFrame->GetCanvas()->SetAbortRequest( false );
701  }
702 
703  CurrPosition.y = initialPos.y;
704 
705  for( ; CurrPosition.y < xylimit.y; CurrPosition.y += RoutingMatrix.m_GridRouting )
706  {
707  // Erase traces.
708  draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
709 
710  fpBBox.SetOrigin( fpBBoxOrg + CurrPosition );
711  g_Offset_Module = mod_pos - CurrPosition;
712  int keepOutCost = TstModuleOnBoard( brd, aModule, TstOtherSide );
713 
714  // Draw at new place
715  color = keepOutCost >= 0 ? BROWN : RED;
716  draw_FootprintRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, color );
717 
718  if( keepOutCost >= 0 ) // i.e. if the module can be put here
719  {
720  error = 0;
721  aFrame->build_ratsnest_module( aModule );
722  curr_cost = compute_Ratsnest_PlaceModule( brd );
723  Score = curr_cost + keepOutCost;
724 
725  if( (min_cost >= Score ) || (min_cost < 0 ) )
726  {
727  LastPosOK = CurrPosition;
728  min_cost = Score;
729  wxString msg;
730  msg.Printf( wxT( "Score %g, pos %s, %s" ),
731  min_cost,
732  GetChars( ::CoordinateToString( LastPosOK.x ) ),
733  GetChars( ::CoordinateToString( LastPosOK.y ) ) );
734  aFrame->SetStatusText( msg );
735  }
736  }
737  }
738  }
739 
740  // erasing the last traces
741  GRRect( aFrame->GetCanvas()->GetClipBox(), aDC, fpBBox, 0, BROWN );
742 
743  displ_opts->m_Show_Module_Ratsnest = showRats;
744 
745  // Regeneration of the modified variable.
746  CurrPosition = LastPosOK;
747 
749 
750  MinCout = min_cost;
751  return error;
752 }
753 
754 
755 /* Test if the rectangular area (ux, ux .. y0, y1):
756  * - is a free zone (except OCCUPED_By_MODULE returns)
757  * - is on the working surface of the board (otherwise returns OUT_OF_BOARD)
758  *
759  * Returns OUT_OF_BOARD, or OCCUPED_By_MODULE or FREE_CELL if OK
760  */
761 int TstRectangle( BOARD* Pcb, const EDA_RECT& aRect, int side )
762 {
763  EDA_RECT rect = aRect;
764 
765  rect.Inflate( RoutingMatrix.m_GridRouting / 2 );
766 
767  wxPoint start = rect.GetOrigin();
768  wxPoint end = rect.GetEnd();
769 
770  start -= RoutingMatrix.m_BrdBox.GetOrigin();
772 
773  int row_min = start.y / RoutingMatrix.m_GridRouting;
774  int row_max = end.y / RoutingMatrix.m_GridRouting;
775  int col_min = start.x / RoutingMatrix.m_GridRouting;
776  int col_max = end.x / RoutingMatrix.m_GridRouting;
777 
778  if( start.y > row_min * RoutingMatrix.m_GridRouting )
779  row_min++;
780 
781  if( start.x > col_min * RoutingMatrix.m_GridRouting )
782  col_min++;
783 
784  if( row_min < 0 )
785  row_min = 0;
786 
787  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
788  row_max = RoutingMatrix.m_Nrows - 1;
789 
790  if( col_min < 0 )
791  col_min = 0;
792 
793  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
794  col_max = RoutingMatrix.m_Ncols - 1;
795 
796  for( int row = row_min; row <= row_max; row++ )
797  {
798  for( int col = col_min; col <= col_max; col++ )
799  {
800  unsigned int data = RoutingMatrix.GetCell( row, col, side );
801 
802  if( ( data & CELL_is_ZONE ) == 0 )
803  return OUT_OF_BOARD;
804 
805  if( (data & CELL_is_MODULE) )
806  return OCCUPED_By_MODULE;
807  }
808  }
809 
810  return FREE_CELL;
811 }
812 
813 
814 /* Calculates and returns the clearance area of the rectangular surface
815  * aRect):
816  * (Sum of cells in terms of distance)
817  */
818 unsigned int CalculateKeepOutArea( const EDA_RECT& aRect, int side )
819 {
820  wxPoint start = aRect.GetOrigin();
821  wxPoint end = aRect.GetEnd();
822 
823  start -= RoutingMatrix.m_BrdBox.GetOrigin();
825 
826  int row_min = start.y / RoutingMatrix.m_GridRouting;
827  int row_max = end.y / RoutingMatrix.m_GridRouting;
828  int col_min = start.x / RoutingMatrix.m_GridRouting;
829  int col_max = end.x / RoutingMatrix.m_GridRouting;
830 
831  if( start.y > row_min * RoutingMatrix.m_GridRouting )
832  row_min++;
833 
834  if( start.x > col_min * RoutingMatrix.m_GridRouting )
835  col_min++;
836 
837  if( row_min < 0 )
838  row_min = 0;
839 
840  if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) )
841  row_max = RoutingMatrix.m_Nrows - 1;
842 
843  if( col_min < 0 )
844  col_min = 0;
845 
846  if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) )
847  col_max = RoutingMatrix.m_Ncols - 1;
848 
849  unsigned int keepOutCost = 0;
850 
851  for( int row = row_min; row <= row_max; row++ )
852  {
853  for( int col = col_min; col <= col_max; col++ )
854  {
855  // RoutingMatrix.GetDist returns the "cost" of the cell
856  // at position (row, col)
857  // in autoplace this is the cost of the cell, if it is
858  // inside aRect
859  keepOutCost += RoutingMatrix.GetDist( row, col, side );
860  }
861  }
862 
863  return keepOutCost;
864 }
865 
866 
867 /* Test if the module can be placed on the board.
868  * Returns the value TstRectangle().
869  * Module is known by its bounding box
870  */
871 int TstModuleOnBoard( BOARD* Pcb, MODULE* aModule, bool TstOtherSide )
872 {
873  int side = TOP;
874  int otherside = BOTTOM;
875 
876  if( aModule->GetLayer() == B_Cu )
877  {
878  side = BOTTOM; otherside = TOP;
879  }
880 
881  EDA_RECT fpBBox = aModule->GetFootprintRect();
882  fpBBox.Move( -g_Offset_Module );
883 
884  int diag = TstRectangle( Pcb, fpBBox, side );
885 
886  if( diag != FREE_CELL )
887  return diag;
888 
889  if( TstOtherSide )
890  {
891  diag = TstRectangle( Pcb, fpBBox, otherside );
892 
893  if( diag != FREE_CELL )
894  return diag;
895  }
896 
897  int marge = ( RoutingMatrix.m_GridRouting * aModule->GetPadCount() ) / GAIN;
898 
899  fpBBox.Inflate( marge );
900  return CalculateKeepOutArea( fpBBox, side );
901 }
902 
903 
905 {
906  double curr_cost;
907  wxPoint start; // start point of a ratsnest
908  wxPoint end; // end point of a ratsnest
909  int dx, dy;
910 
911  if( ( aBrd->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 )
912  return -1;
913 
914  curr_cost = 0;
915 
916  for( unsigned ii = 0; ii < aBrd->m_LocalRatsnest.size(); ii++ )
917  {
918  RATSNEST_ITEM* pt_local_rats_nest = &aBrd->m_LocalRatsnest[ii];
919 
920  if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) )
921  continue; // Skip ratsnest between 2 pads of the current module
922 
923  // Skip modules not inside the board area
924  MODULE* module = pt_local_rats_nest->m_PadEnd->GetParent();
925 
926  if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) )
927  continue;
928 
929  start = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module;
930  end = pt_local_rats_nest->m_PadEnd->GetPosition();
931 
932  // Cost of the ratsnest.
933  dx = end.x - start.x;
934  dy = end.y - start.y;
935 
936  dx = abs( dx );
937  dy = abs( dy );
938 
939  // ttry to have always dx >= dy to calculate the cost of the rastsnet
940  if( dx < dy )
941  std::swap( dx, dy );
942 
943  // Cost of the connection = length + penalty due to the slope
944  // dx is the biggest length relative to the X or Y axis
945  // the penalty is max for 45 degrees ratsnests,
946  // and 0 for horizontal or vertical ratsnests.
947  // For Horizontal and Vertical ratsnests, dy = 0;
948  double conn_cost = hypot( dx, dy * 2.0 );
949  curr_cost += conn_cost; // Total cost = sum of costs of each connection
950  }
951 
952  return curr_cost;
953 }
954 
955 
966 void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1,
967  int marge, int aKeepOut, LSET aLayerMask )
968 {
969  int row, col;
970  int row_min, row_max, col_min, col_max, pmarge;
971  int trace = 0;
972  DIST_CELL data, LocalKeepOut;
973  int lgain, cgain;
974 
975  if( aLayerMask[g_Route_Layer_BOTTOM] )
976  trace = 1; // Trace on bottom layer.
977 
979  trace |= 2; // Trace on top layer.
980 
981  if( trace == 0 )
982  return;
983 
984  ux0 -= RoutingMatrix.m_BrdBox.GetX();
985  uy0 -= RoutingMatrix.m_BrdBox.GetY();
986  ux1 -= RoutingMatrix.m_BrdBox.GetX();
987  uy1 -= RoutingMatrix.m_BrdBox.GetY();
988 
989  ux0 -= marge; ux1 += marge;
990  uy0 -= marge; uy1 += marge;
991 
992  pmarge = marge / RoutingMatrix.m_GridRouting;
993 
994  if( pmarge < 1 )
995  pmarge = 1;
996 
997  // Calculate the coordinate limits of the rectangle.
998  row_max = uy1 / RoutingMatrix.m_GridRouting;
999  col_max = ux1 / RoutingMatrix.m_GridRouting;
1000  row_min = uy0 / RoutingMatrix.m_GridRouting;
1001 
1002  if( uy0 > row_min * RoutingMatrix.m_GridRouting )
1003  row_min++;
1004 
1005  col_min = ux0 / RoutingMatrix.m_GridRouting;
1006 
1007  if( ux0 > col_min * RoutingMatrix.m_GridRouting )
1008  col_min++;
1009 
1010  if( row_min < 0 )
1011  row_min = 0;
1012 
1013  if( row_max >= (RoutingMatrix.m_Nrows - 1) )
1014  row_max = RoutingMatrix.m_Nrows - 1;
1015 
1016  if( col_min < 0 )
1017  col_min = 0;
1018 
1019  if( col_max >= (RoutingMatrix.m_Ncols - 1) )
1020  col_max = RoutingMatrix.m_Ncols - 1;
1021 
1022  for( row = row_min; row <= row_max; row++ )
1023  {
1024  lgain = 256;
1025 
1026  if( row < pmarge )
1027  lgain = ( 256 * row ) / pmarge;
1028  else if( row > row_max - pmarge )
1029  lgain = ( 256 * ( row_max - row ) ) / pmarge;
1030 
1031  for( col = col_min; col <= col_max; col++ )
1032  {
1033  // RoutingMatrix Dist map containt the "cost" of the cell
1034  // at position (row, col)
1035  // in autoplace this is the cost of the cell, when
1036  // a footprint overlaps it, near a "master" footprint
1037  // this cost is hight near the "master" footprint
1038  // and decrease with the distance
1039  cgain = 256;
1040  LocalKeepOut = aKeepOut;
1041 
1042  if( col < pmarge )
1043  cgain = ( 256 * col ) / pmarge;
1044  else if( col > col_max - pmarge )
1045  cgain = ( 256 * ( col_max - col ) ) / pmarge;
1046 
1047  cgain = ( cgain * lgain ) / 256;
1048 
1049  if( cgain != 256 )
1050  LocalKeepOut = ( LocalKeepOut * cgain ) / 256;
1051 
1052  if( trace & 1 )
1053  {
1054  data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut;
1055  RoutingMatrix.SetDist( row, col, BOTTOM, data );
1056  }
1057 
1058  if( trace & 2 )
1059  {
1060  data = RoutingMatrix.GetDist( row, col, TOP );
1061  data = std::max( data, LocalKeepOut );
1062  RoutingMatrix.SetDist( row, col, TOP, data );
1063  }
1064  }
1065  }
1066 }
1067 
1068 
1069 // Sort routines
1070 static bool Tri_PlaceModules( MODULE* ref, MODULE* compare )
1071 {
1072  double ff1, ff2;
1073 
1074  ff1 = ref->GetArea() * ref->GetPadCount();
1075  ff2 = compare->GetArea() * compare->GetPadCount();
1076 
1077  return ff2 < ff1;
1078 }
1079 
1080 
1081 static bool sortFootprintsByRatsnestSize( MODULE* ref, MODULE* compare )
1082 {
1083  double ff1, ff2;
1084 
1085  ff1 = ref->GetArea() * ref->GetFlag();
1086  ff2 = compare->GetArea() * compare->GetFlag();
1087  return ff2 < ff1;
1088 }
1089 
1090 
1098 static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
1099 {
1100  MODULE* Module;
1101  std::vector <MODULE*> moduleList;
1102 
1103  // Build sorted footprints list (sort by decreasing size )
1104  Module = pcbframe->GetBoard()->m_Modules;
1105 
1106  for( ; Module != NULL; Module = Module->Next() )
1107  {
1108  Module->CalculateBoundingBox();
1109  moduleList.push_back( Module );
1110  }
1111 
1112  sort( moduleList.begin(), moduleList.end(), Tri_PlaceModules );
1113 
1114  for( unsigned kk = 0; kk < moduleList.size(); kk++ )
1115  {
1116  Module = moduleList[kk];
1117  Module->SetFlag( 0 );
1118 
1119  if( !Module->NeedsPlaced() )
1120  continue;
1121 
1122  pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
1123  pcbframe->SetMsgPanel( Module );
1124  pcbframe->build_ratsnest_module( Module );
1125 
1126  // Calculate external ratsnest.
1127  for( unsigned ii = 0; ii < pcbframe->GetBoard()->m_LocalRatsnest.size(); ii++ )
1128  {
1129  if( ( pcbframe->GetBoard()->m_LocalRatsnest[ii].m_Status &
1130  LOCAL_RATSNEST_ITEM ) == 0 )
1131  Module->IncrementFlag();
1132  }
1133  }
1134 
1135  pcbframe->GetBoard()->m_Status_Pcb &= ~RATSNEST_ITEM_LOCAL_OK;
1136 
1137  sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
1138 
1139  // Search for "best" module.
1140  MODULE* bestModule = NULL;
1141  MODULE* altModule = NULL;
1142 
1143  for( unsigned ii = 0; ii < moduleList.size(); ii++ )
1144  {
1145  Module = moduleList[ii];
1146 
1147  if( !Module->NeedsPlaced() )
1148  continue;
1149 
1150  altModule = Module;
1151 
1152  if( Module->GetFlag() == 0 )
1153  continue;
1154 
1155  bestModule = Module;
1156  break;
1157  }
1158 
1159  if( bestModule )
1160  return bestModule;
1161  else
1162  return altModule;
1163 }
1164 
1165 
1191 {
1192  int row, col;
1193  long current_cell, old_cell_H;
1194  std::vector<long> pt_cell_V;
1195  int nbpoints = 0;
1196 
1197 #define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE)
1198 
1199  pt_cell_V.reserve( std::max( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) );
1200  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1201 
1202  // Search from left to right and top to bottom.
1203  for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
1204  {
1205  old_cell_H = 0;
1206 
1207  for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
1208  {
1209  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1210 
1211  if( current_cell == 0 ) // a free cell is found
1212  {
1213  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
1214  {
1215  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1216  current_cell = CELL_is_ZONE;
1217  nbpoints++;
1218  }
1219  }
1220 
1221  pt_cell_V[col] = old_cell_H = current_cell;
1222  }
1223  }
1224 
1225  // Search from right to left and top to bottom/
1226  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1227 
1228  for( row = 0; row < RoutingMatrix.m_Nrows; row++ )
1229  {
1230  old_cell_H = 0;
1231 
1232  for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
1233  {
1234  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1235 
1236  if( current_cell == 0 ) // a free cell is found
1237  {
1238  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) )
1239  {
1240  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1241  current_cell = CELL_is_ZONE;
1242  nbpoints++;
1243  }
1244  }
1245 
1246  pt_cell_V[col] = old_cell_H = current_cell;
1247  }
1248  }
1249 
1250  // Search from bottom to top and right to left.
1251  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1252 
1253  for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- )
1254  {
1255  old_cell_H = 0;
1256 
1257  for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
1258  {
1259  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1260 
1261  if( current_cell == 0 ) // a free cell is found
1262  {
1263  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
1264  {
1265  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1266  current_cell = CELL_is_ZONE;
1267  nbpoints++;
1268  }
1269  }
1270 
1271  pt_cell_V[row] = old_cell_H = current_cell;
1272  }
1273  }
1274 
1275  // Search from bottom to top and left to right.
1276  fill( pt_cell_V.begin(), pt_cell_V.end(), 0 );
1277 
1278  for( col = 0; col < RoutingMatrix.m_Ncols; col++ )
1279  {
1280  old_cell_H = 0;
1281 
1282  for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- )
1283  {
1284  current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE;
1285 
1286  if( current_cell == 0 ) // a free cell is found
1287  {
1288  if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) )
1289  {
1290  RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE );
1291  current_cell = CELL_is_ZONE;
1292  nbpoints++;
1293  }
1294  }
1295 
1296  pt_cell_V[row] = old_cell_H = current_cell;
1297  }
1298  }
1299 
1300  return nbpoints;
1301 }
std::vector< RATSNEST_ITEM > m_LocalRatsnest
Ratsnest list relative to a given footprint (used while moving a footprint).
Definition: class_board.h:251
int GetFlag() const
Definition: class_module.h:189
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
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, LSET side, int color, int op_logic)
Definition: graphpcb.cpp:478
static wxPoint CurrPosition
wxPoint g_Offset_Module
Definition: pcbnew.cpp:83
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:188
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)
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:143
static bool sortFootprintsByRatsnestSize(MODULE *ref, MODULE *compare)
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
virtual void SetLayer(LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
MODULE * Next() const
Definition: class_module.h:99
MODULE * GetParent() const
Definition: class_pad.h:108
void SetNeedsPlaced(bool needsPlaced)
Definition: class_module.h:251
int GetHeight() const
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
LAYER_ID g_Route_Layer_TOP
Definition: pcbnew.cpp:78
void SetOrigin(const wxPoint &pos)
BOARD * GetBoard() const
void Rotate_Module(wxDC *DC, MODULE *module, double angle, bool incremental)
Definition: modules.cpp:430
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
EDA_ITEM * Next() const
Definition: base_struct.h:206
bool NeedsPlaced() const
Definition: class_module.h:250
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:523
class EDA_MSG_PANEL is a panel to display various information messages.
Definition: msgpanel.h:111
LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
#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:113
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:351
#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:839
const wxPoint & GetOrigin() const
D_PAD * m_PadEnd
Definition: class_netinfo.h:76
#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
Class LSET is a set of 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:751
MATRIX_CELL * m_BoardSide[MAX_ROUTING_LAYERS_COUNT]
Definition: autorout.h:107
double GetOrientation() const
Definition: class_module.h:147
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
void build_ratsnest_module(MODULE *aModule)
Function build_ratsnest_module Build a ratsnest relative to one footprint.
Definition: ratsnest.cpp:533
const wxPoint & GetPosition() const override
Definition: class_pad.h:170
Definition: colors.h:59
DIST_CELL GetDist(int aRow, int aCol, int aSide)
D_PAD * Next() const
Definition: class_pad.h:106
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:242
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:242
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:223
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:165
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.
D_PAD * m_PadStart
Definition: class_netinfo.h:75
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
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:515
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
LAYER_ID
Enum LAYER_ID is the set of PCB layers.
DLIST< MODULE > m_Modules
Definition: class_board.h:243
#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
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
int GetWidth() const
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:455
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
DLIST< D_PAD > & Pads()
Definition: class_module.h:133
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: modules.cpp:492
Class RATSNEST_ITEM describes a ratsnest line: a straight line connecting 2 pads. ...
Definition: class_netinfo.h:68
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:520
#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
LAYER_ID g_Route_Layer_BOTTOM
Definition: pcbnew.cpp:79
void SetFlag(int aFlag)
Definition: class_module.h:187
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:240
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