KiCad PCB EDA Suite
AR_AUTOPLACER Class Reference

#include <ar_autoplacer.h>

Public Member Functions

 AR_AUTOPLACER (BOARD *aBoard)
 
AR_RESULT AutoplaceModules (std::vector< MODULE * > aModules, BOARD_COMMIT *aCommit, bool aPlaceOffboardModules=false)
 
const std::vector< MODULE * > QueryOffboardModules ()
 
void SetPlacementGrid (int aGrid)
 
void SetOverlay (std::shared_ptr< KIGFX::VIEW_OVERLAY > aOverlay)
 Set a VIEW overlay to draw items during a autoplace session. More...
 
void SetRefreshCallback (std::function< int(MODULE *aModule)> aCallback)
 a callback function to redraw on screen the view after changes, for instance after moving a footprint More...
 
void SetProgressReporter (PROGRESS_REPORTER *aReporter)
 

Private Member Functions

void drawPlacementRoutingMatrix ()
 
void rotateModule (MODULE *module, double angle, bool incremental)
 
int genPlacementRoutingMatrix ()
 
bool fillMatrix ()
 fills m_matrix cells from m_boardShape. More...
 
void genModuleOnRoutingMatrix (MODULE *Module)
 
int testRectangle (const EDA_RECT &aRect, int side)
 
int testModuleByPolygon (MODULE *aModule, int aSide, const wxPoint &aOffset)
 
unsigned int calculateKeepOutArea (const EDA_RECT &aRect, int side)
 
int testModuleOnBoard (MODULE *aModule, bool TstOtherSide, const wxPoint &aOffset)
 
int getOptimalModulePlacement (MODULE *aModule)
 
double computePlacementRatsnestCost (MODULE *aModule, const wxPoint &aOffset)
 
MODULEpickModule ()
 Find the "best" module place. More...
 
void placeModule (MODULE *aModule, bool aDoNotRecreateRatsnest, const wxPoint &aPos)
 
const D_PADnearestPad (MODULE *aRefModule, D_PAD *aRefPad, const wxPoint &aOffset)
 
void addFpBody (wxPoint aStart, wxPoint aEnd, LSET aLayerMask)
 
void addPad (D_PAD *aPad, int aClearance)
 
void buildFpAreas (MODULE *aFootprint, int aFpClearance)
 

Private Attributes

AR_MATRIX m_matrix
 
SHAPE_POLY_SET m_topFreeArea
 
SHAPE_POLY_SET m_bottomFreeArea
 
SHAPE_POLY_SET m_boardShape
 
SHAPE_POLY_SET m_fpAreaTop
 
SHAPE_POLY_SET m_fpAreaBottom
 
BOARDm_board
 
wxPoint m_curPosition
 
wxPoint m_moduleOffset
 
double m_minCost
 
int m_gridSize
 
std::shared_ptr< KIGFX::VIEW_OVERLAYm_overlay
 
std::unique_ptr< CONNECTIVITY_DATAm_connectivity
 
std::function< int(MODULE *aModule)> m_refreshCallback
 
PROGRESS_REPORTERm_progressReporter
 

Detailed Description

Definition at line 58 of file ar_autoplacer.h.

Constructor & Destructor Documentation

AR_AUTOPLACER::AR_AUTOPLACER ( BOARD aBoard)

Definition at line 79 of file ar_autoplacer.cpp.

References m_board, m_connectivity, m_gridSize, m_progressReporter, m_refreshCallback, mod, BOARD::Modules(), and STEP_AR_MM.

80 {
81  m_board = aBoard;
82  m_connectivity.reset( new CONNECTIVITY_DATA );
83 
84  for( auto mod : m_board->Modules() )
85  m_connectivity->Add( mod );
86 
87  m_gridSize = Millimeter2iu( STEP_AR_MM );
88  m_progressReporter = nullptr;
89  m_refreshCallback = nullptr;
90 }
PROGRESS_REPORTER * m_progressReporter
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
#define STEP_AR_MM
std::function< int(MODULE *aModule)> m_refreshCallback
#define mod(a, n)
Definition: greymap.cpp:24
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity

Member Function Documentation

void AR_AUTOPLACER::addFpBody ( wxPoint  aStart,
wxPoint  aEnd,
LSET  aLayerMask 
)
private

Definition at line 287 of file ar_autoplacer.cpp.

References SHAPE_POLY_SET::Append(), B_Cu, F_Cu, m_fpAreaBottom, m_fpAreaTop, and SHAPE_POLY_SET::NewOutline().

Referenced by buildFpAreas(), and SetProgressReporter().

288 {
289  // Add a polygonal shape (rectangle) to m_fpAreaFront and/or m_fpAreaBack
290  if( aLayerMask[ F_Cu ] )
291  {
293  m_fpAreaTop.Append( aStart.x, aStart.y );
294  m_fpAreaTop.Append( aEnd.x, aStart.y );
295  m_fpAreaTop.Append( aEnd.x, aEnd.y );
296  m_fpAreaTop.Append( aStart.x, aEnd.y );
297  }
298  if( aLayerMask[ B_Cu ] )
299  {
301  m_fpAreaBottom.Append( aStart.x, aStart.y );
302  m_fpAreaBottom.Append( aEnd.x, aStart.y );
303  m_fpAreaBottom.Append( aEnd.x, aEnd.y );
304  m_fpAreaBottom.Append( aStart.x, aEnd.y );
305  }
306 }
SHAPE_POLY_SET m_fpAreaBottom
SHAPE_POLY_SET m_fpAreaTop
int NewOutline()
Creates a new empty polygon in the set and returns its index
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
void AR_AUTOPLACER::addPad ( D_PAD aPad,
int  aClearance 
)
private

Definition at line 308 of file ar_autoplacer.cpp.

References SHAPE_POLY_SET::Append(), B_Cu, F_Cu, EDA_RECT::GetBottom(), D_PAD::GetBoundingBox(), EDA_RECT::GetLeft(), EDA_RECT::GetRight(), EDA_RECT::GetTop(), EDA_RECT::Inflate(), D_PAD::IsOnLayer(), m_fpAreaBottom, m_fpAreaTop, and SHAPE_POLY_SET::NewOutline().

Referenced by buildFpAreas(), and SetProgressReporter().

309 {
310  // Add a polygonal shape (rectangle) to m_fpAreaFront and/or m_fpAreaBack
311  EDA_RECT bbox = aPad->GetBoundingBox();
312  bbox.Inflate( aClearance );
313 
314  if( aPad->IsOnLayer( F_Cu ) )
315  {
317  m_fpAreaTop.Append( bbox.GetLeft(), bbox.GetTop() );
318  m_fpAreaTop.Append( bbox.GetRight(), bbox.GetTop() );
319  m_fpAreaTop.Append( bbox.GetRight(), bbox.GetBottom() );
320  m_fpAreaTop.Append( bbox.GetLeft(), bbox.GetBottom() );
321  }
322  if( aPad->IsOnLayer( B_Cu ) )
323  {
325  m_fpAreaBottom.Append( bbox.GetLeft(), bbox.GetTop() );
326  m_fpAreaBottom.Append( bbox.GetRight(), bbox.GetTop() );
327  m_fpAreaBottom.Append( bbox.GetRight(), bbox.GetBottom() );
328  m_fpAreaBottom.Append( bbox.GetLeft(), bbox.GetBottom() );
329  }
330 }
int GetLeft() const
Definition: eda_rect.h:120
SHAPE_POLY_SET m_fpAreaBottom
int GetBottom() const
Definition: eda_rect.h:122
SHAPE_POLY_SET m_fpAreaTop
int GetRight() const
Definition: eda_rect.h:119
int NewOutline()
Creates a new empty polygon in the set and returns its index
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:663
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Definition: class_pad.cpp:215
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
int GetTop() const
Definition: eda_rect.h:121
AR_RESULT AR_AUTOPLACER::AutoplaceModules ( std::vector< MODULE * >  aModules,
BOARD_COMMIT aCommit,
bool  aPlaceOffboardModules = false 
)

Definition at line 898 of file ar_autoplacer.cpp.

References PROGRESS_REPORTER::AdvanceProgress(), AR_ABORT_PLACEMENT, AR_CANCELLED, AR_COMPLETED, AR_FAILURE, MODULE::CalculateBoundingBox(), EDA_RECT::Contains(), drawPlacementRoutingMatrix(), Format(), genModuleOnRoutingMatrix(), genPlacementRoutingMatrix(), getOptimalModulePlacement(), MODULE::GetOrientation(), MODULE::GetPlacementCost180(), MODULE::GetPlacementCost90(), MODULE::GetReference(), PROGRESS_REPORTER::KeepRefreshing(), m_board, AR_MATRIX::m_BrdBox, m_curPosition, AR_MATRIX::m_GridRouting, m_gridSize, m_matrix, m_minCost, m_progressReporter, m_refreshCallback, COMMIT::Modify(), BOARD::Modules(), OrientationPenalty, pickModule(), placeModule(), PROGRESS_REPORTER::Report(), rotateModule(), MODULE::SetIsPlaced(), PROGRESS_REPORTER::SetMaxProgress(), MODULE::SetNeedsPlaced(), PROGRESS_REPORTER::SetTitle(), and AR_MATRIX::UnInitRoutingMatrix().

Referenced by AUTOPLACE_TOOL::autoplace().

900 {
901  wxPoint PosOK;
902  wxPoint memopos;
903  int error;
904  MODULE* module = nullptr;
905  bool cancelled = false;
906 
907  memopos = m_curPosition;
908 
909  //printf("set grid: %d\n", m_gridSize);
910 
911  m_matrix.m_GridRouting = m_gridSize; //(int) m_frame->GetScreen()->GetGridSize().x;
912 
913  // Ensure Board.m_GridRouting has a reasonable value:
914  if( m_matrix.m_GridRouting < Millimeter2iu( 0.25 ) )
915  m_matrix.m_GridRouting = Millimeter2iu( 0.25 );
916 
917  // Compute module parameters used in auto place
918  if( genPlacementRoutingMatrix( ) == 0 )
919  return AR_FAILURE;
920 
921  int moduleCount = 0;
922 
923  for ( auto m : m_board->Modules() )
924  {
925  m->SetNeedsPlaced( false );
926  }
927 
928  std::vector<MODULE *> offboardMods;
929 
930  if( aPlaceOffboardModules )
931  {
932  for ( auto m : m_board->Modules() )
933  {
934  if( !m_matrix.m_BrdBox.Contains( m->GetPosition() ) )
935  {
936  offboardMods.push_back( m );
937  }
938  }
939  }
940 
941  for ( auto m : aModules )
942  {
943  m->SetNeedsPlaced( true );
944  aCommit->Modify(m);
945  }
946 
947  for ( auto m : offboardMods )
948  {
949  m->SetNeedsPlaced( true );
950  aCommit->Modify(m);
951  }
952 
953  for ( auto m : m_board->Modules() )
954  {
955  if( m->NeedsPlaced() ) // Erase from screen
956  moduleCount++;
957  else
959  }
960 
961 
962  int cnt = 0;
963  wxString msg;
964 
965  if( m_progressReporter )
966  {
967  m_progressReporter->Report( _( "Autoplacing components..." ) );
968  m_progressReporter->SetMaxProgress( moduleCount );
969  }
970 
972 
973  if( m_refreshCallback )
974  m_refreshCallback( nullptr );
975 
976 
977  while( ( module = pickModule( ) ) != nullptr )
978  {
979  // Display some info about activity, module placement can take a while:
980  //m_frame->SetStatusText( msg );
981 
982  if( m_progressReporter )
984  _( "Autoplacing %s" ), module->GetReference() ) );
985 
986  double initialOrient = module->GetOrientation();
987 
988  error = getOptimalModulePlacement( module );
989  double bestScore = m_minCost;
990  double bestRotation = 0.0;
991  int rotAllowed;
992  PosOK = m_curPosition;
993 
994  if( error == AR_ABORT_PLACEMENT )
995  goto end_of_tst;
996 
997  // Try orientations 90, 180, 270 degrees from initial orientation
998  rotAllowed = module->GetPlacementCost180();
999 
1000  //printf("rotAllowed %d\n", rotAllowed);
1001 
1002  if( rotAllowed != 0 )
1003  {
1004  rotateModule( module, 1800.0, true );
1005  error = getOptimalModulePlacement( module );
1006  m_minCost *= OrientationPenalty[rotAllowed];
1007 
1008  if( bestScore > m_minCost ) // This orientation is better.
1009  {
1010  PosOK = m_curPosition;
1011  bestScore = m_minCost;
1012  bestRotation = 1800.0;
1013  }
1014  else
1015  {
1016  rotateModule( module, initialOrient, false );
1017  }
1018 
1019  if( error == AR_ABORT_PLACEMENT )
1020  goto end_of_tst;
1021  }
1022 
1023  // Determine if the best orientation of a module is 90.
1024  rotAllowed = module->GetPlacementCost90();
1025 
1026  if( rotAllowed != 0 )
1027  {
1028  rotateModule( module, 900.0, true );
1029  error = getOptimalModulePlacement( module );
1030  m_minCost *= OrientationPenalty[rotAllowed];
1031 
1032  if( bestScore > m_minCost ) // This orientation is better.
1033  {
1034  PosOK = m_curPosition;
1035  bestScore = m_minCost;
1036  bestRotation = 900.0;
1037  }
1038  else
1039  {
1040  rotateModule( module, initialOrient, false );
1041  }
1042 
1043  if( error == AR_ABORT_PLACEMENT )
1044  goto end_of_tst;
1045  }
1046 
1047  // Determine if the best orientation of a module is -90.
1048  if( rotAllowed != 0 )
1049  {
1050  rotateModule( module, 2700.0, true );
1051  error = getOptimalModulePlacement( module );
1052  m_minCost *= OrientationPenalty[rotAllowed];
1053 
1054  if( bestScore > m_minCost ) // This orientation is better.
1055  {
1056  PosOK = m_curPosition;
1057  bestScore = m_minCost;
1058  bestRotation = 2700.0;
1059  }
1060  else
1061  {
1062  rotateModule( module, initialOrient, false );
1063  }
1064 
1065  if( error == AR_ABORT_PLACEMENT )
1066  goto end_of_tst;
1067  }
1068 
1069 end_of_tst:
1070 
1071  if( error == AR_ABORT_PLACEMENT )
1072  break;
1073 
1074 
1075  bestRotation += initialOrient;
1076 
1077  if( bestRotation != module->GetOrientation() )
1078  {
1079  //printf("best rotation %d\n", bestRotation );
1080  rotateModule( module, bestRotation, false );
1081  }
1082 
1083  // Place module.
1084  placeModule( module, true, m_curPosition );
1085 
1086  module->CalculateBoundingBox();
1087  genModuleOnRoutingMatrix( module );
1088  module->SetIsPlaced( true );
1089  module->SetNeedsPlaced( false );
1091 
1092  if( m_refreshCallback )
1093  m_refreshCallback( module );
1094 
1095 
1096  if( m_progressReporter )
1097  {
1099 
1100  if ( !m_progressReporter->KeepRefreshing( false ) )
1101  {
1102  cancelled = true;
1103  break;
1104  }
1105  }
1106  cnt++;
1107  }
1108 
1109  m_curPosition = memopos;
1110 
1112 
1113  for ( auto m : m_board->Modules() )
1114  {
1115  m->CalculateBoundingBox();
1116  }
1117 
1118  return cancelled ? AR_CANCELLED : AR_COMPLETED;
1119 }
void rotateModule(MODULE *module, double angle, bool incremental)
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
PROGRESS_REPORTER * m_progressReporter
void placeModule(MODULE *aModule, bool aDoNotRecreateRatsnest, const wxPoint &aPos)
bool Contains(const wxPoint &aPoint) const
Function Contains.
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
int m_GridRouting
Definition: ar_matrix.h:63
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
void SetNeedsPlaced(bool needsPlaced)
Definition: class_module.h:295
void Report(const wxString &aMessage)
Display aMessage in the progress bar dialog.
int GetPlacementCost90() const
Definition: class_module.h:582
void genModuleOnRoutingMatrix(MODULE *Module)
AR_MATRIX m_matrix
void drawPlacementRoutingMatrix()
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
int getOptimalModulePlacement(MODULE *aModule)
double GetOrientation() const
Definition: class_module.h:188
int genPlacementRoutingMatrix()
#define AR_ABORT_PLACEMENT
MODULE * pickModule()
Find the "best" module place.
void SetIsPlaced(bool isPlaced)
Definition: class_module.h:286
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:140
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:462
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
std::function< int(MODULE *aModule)> m_refreshCallback
static const double OrientationPenalty[11]
wxPoint m_curPosition
void SetMaxProgress(int aMaxProgress)
Fix the value thar gives the 100 precent progress bar length (inside the current virtual zone) ...
virtual void SetTitle(const wxString &aTitle)
change the title displayed on the window caption MUST only be called from the main thread...
void AdvanceProgress()
Increment the progress bar length (inside the current virtual zone)
int GetPlacementCost180() const
Definition: class_module.h:579
void AR_AUTOPLACER::buildFpAreas ( MODULE aFootprint,
int  aFpClearance 
)
private

Definition at line 333 of file ar_autoplacer.cpp.

References addFpBody(), addPad(), B_Cu, MODULE::BuildPolyCourtyard(), F_Cu, MODULE::GetBoundingBox(), EDA_RECT::GetEnd(), BOARD_ITEM::GetLayer(), EDA_RECT::GetOrigin(), MODULE::GetPolyCourtyardBack(), MODULE::GetPolyCourtyardFront(), EDA_RECT::Inflate(), m_fpAreaBottom, m_fpAreaTop, AR_MATRIX::m_GridRouting, m_matrix, MODULE::Pads(), and SHAPE_POLY_SET::RemoveAllContours().

Referenced by genModuleOnRoutingMatrix(), SetProgressReporter(), and testModuleOnBoard().

334 {
337 
338  if( aFootprint->BuildPolyCourtyard() )
339  {
340  m_fpAreaTop = aFootprint->GetPolyCourtyardFront();
341  m_fpAreaBottom = aFootprint->GetPolyCourtyardBack();
342  }
343 
344  LSET layerMask;
345 
346  if( aFootprint->GetLayer() == F_Cu )
347  layerMask.set( F_Cu );
348 
349  if( aFootprint->GetLayer() == B_Cu )
350  layerMask.set( B_Cu );
351 
352  EDA_RECT fpBBox = aFootprint->GetBoundingBox();
353 
354  fpBBox.Inflate( ( m_matrix.m_GridRouting / 2 ) + aFpClearance );
355 
356  // Add a minimal area to the fp area:
357  addFpBody( fpBBox.GetOrigin(), fpBBox.GetEnd(), layerMask );
358 
359  // Trace pads + clearance areas.
360  for( auto pad : aFootprint->Pads() )
361  {
362  int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
363  addPad( pad, margin );
364  }
365 }
SHAPE_POLY_SET & GetPolyCourtyardFront()
Used in DRC to test the courtyard area (a complex polygon)
Definition: class_module.h:711
bool BuildPolyCourtyard()
Used in DRC to build the courtyard area (a complex polygon) from graphic items put on the courtyard...
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int m_GridRouting
Definition: ar_matrix.h:63
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:168
void addPad(D_PAD *aPad, int aClearance)
AR_MATRIX m_matrix
SHAPE_POLY_SET m_fpAreaBottom
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Class LSET is a set of PCB_LAYER_IDs.
SHAPE_POLY_SET m_fpAreaTop
const wxPoint GetEnd() const
Definition: eda_rect.h:114
void addFpBody(wxPoint aStart, wxPoint aEnd, LSET aLayerMask)
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
SHAPE_POLY_SET & GetPolyCourtyardBack()
Definition: class_module.h:712
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
unsigned int AR_AUTOPLACER::calculateKeepOutArea ( const EDA_RECT aRect,
int  side 
)
private

Definition at line 512 of file ar_autoplacer.cpp.

References AR_MATRIX::GetDist(), EDA_RECT::GetEnd(), EDA_RECT::GetOrigin(), AR_MATRIX::m_BrdBox, AR_MATRIX::m_GridRouting, m_matrix, AR_MATRIX::m_Ncols, and AR_MATRIX::m_Nrows.

Referenced by SetProgressReporter(), and testModuleOnBoard().

513 {
514  wxPoint start = aRect.GetOrigin();
515  wxPoint end = aRect.GetEnd();
516 
517  start -= m_matrix.m_BrdBox.GetOrigin();
518  end -= m_matrix.m_BrdBox.GetOrigin();
519 
520  int row_min = start.y / m_matrix.m_GridRouting;
521  int row_max = end.y / m_matrix.m_GridRouting;
522  int col_min = start.x / m_matrix.m_GridRouting;
523  int col_max = end.x / m_matrix.m_GridRouting;
524 
525  if( start.y > row_min * m_matrix.m_GridRouting )
526  row_min++;
527 
528  if( start.x > col_min * m_matrix.m_GridRouting )
529  col_min++;
530 
531  if( row_min < 0 )
532  row_min = 0;
533 
534  if( row_max >= ( m_matrix.m_Nrows - 1 ) )
535  row_max = m_matrix.m_Nrows - 1;
536 
537  if( col_min < 0 )
538  col_min = 0;
539 
540  if( col_max >= ( m_matrix.m_Ncols - 1 ) )
541  col_max = m_matrix.m_Ncols - 1;
542 
543  unsigned int keepOutCost = 0;
544 
545  for( int row = row_min; row <= row_max; row++ )
546  {
547  for( int col = col_min; col <= col_max; col++ )
548  {
549  // m_matrix.GetDist returns the "cost" of the cell
550  // at position (row, col)
551  // in autoplace this is the cost of the cell, if it is
552  // inside aRect
553  keepOutCost += m_matrix.GetDist( row, col, side );
554  }
555  }
556 
557  return keepOutCost;
558 }
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
int m_Ncols
Definition: ar_matrix.h:65
int m_GridRouting
Definition: ar_matrix.h:63
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
AR_MATRIX m_matrix
int m_Nrows
Definition: ar_matrix.h:65
const wxPoint GetEnd() const
Definition: eda_rect.h:114
DIST_CELL GetDist(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:259
double AR_AUTOPLACER::computePlacementRatsnestCost ( MODULE aModule,
const wxPoint &  aOffset 
)
private

Definition at line 731 of file ar_autoplacer.cpp.

References abs, nearestPad(), MODULE::Pads(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by getOptimalModulePlacement(), and SetProgressReporter().

732 {
733  double curr_cost;
734  VECTOR2I start; // start point of a ratsnest
735  VECTOR2I end; // end point of a ratsnest
736  int dx, dy;
737 
738  curr_cost = 0;
739 
740  for ( auto pad : aModule->Pads() )
741  {
742  auto nearest = nearestPad( aModule, pad, aOffset );
743 
744  if( !nearest )
745  continue;
746 
747  //printf("pad %s nearest %s\n", (const char *)aModule->GetReference().c_str(), (const char *)nearest->GetParent()->GetReference().c_str());
748 
749  start = VECTOR2I( pad->GetPosition() ) - VECTOR2I(aOffset);
750  end = VECTOR2I( nearest->GetPosition() );
751 
752  //m_overlay->SetIsStroke( true );
753  //m_overlay->SetStrokeColor( COLOR4D(0.0, 1.0, 0.0, 1.0) );
754  //m_overlay->Line( start, end );
755 
756  // Cost of the ratsnest.
757  dx = end.x - start.x;
758  dy = end.y - start.y;
759 
760  dx = abs( dx );
761  dy = abs( dy );
762 
763  // ttry to have always dx >= dy to calculate the cost of the rastsnet
764  if( dx < dy )
765  std::swap( dx, dy );
766 
767  // Cost of the connection = length + penalty due to the slope
768  // dx is the biggest length relative to the X or Y axis
769  // the penalty is max for 45 degrees ratsnests,
770  // and 0 for horizontal or vertical ratsnests.
771  // For Horizontal and Vertical ratsnests, dy = 0;
772  double conn_cost = hypot( dx, dy * 2.0 );
773  curr_cost += conn_cost; // Total cost = sum of costs of each connection
774  }
775 
776  return curr_cost;
777 }
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:168
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
#define abs(a)
Definition: auxiliary.h:84
const D_PAD * nearestPad(MODULE *aRefModule, D_PAD *aRefPad, const wxPoint &aOffset)
void AR_AUTOPLACER::drawPlacementRoutingMatrix ( )
private

Definition at line 867 of file ar_autoplacer.cpp.

References SHAPE_POLY_SET::Fracture(), m_bottomFreeArea, m_overlay, m_topFreeArea, SHAPE_POLY_SET::OutlineCount(), and SHAPE_POLY_SET::PM_FAST.

Referenced by AutoplaceModules(), and SetProgressReporter().

868 {
869  // Draw the board free area
870  m_overlay->Clear();
871  m_overlay->SetIsFill( true );
872  m_overlay->SetIsStroke( false );
873 
874  SHAPE_POLY_SET freeArea = m_topFreeArea;
875  freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
876 
877  // Draw the free polygon areas, top side:
878  if( freeArea.OutlineCount() > 0 )
879  {
880  m_overlay->SetIsFill( true );
881  m_overlay->SetIsStroke( false );
882  m_overlay->SetFillColor( COLOR4D(0.7, 0.0, 0.1, 0.2) );
883  m_overlay->Polygon( freeArea );
884  }
885 
886  freeArea = m_bottomFreeArea;
887  freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
888 
889  // Draw the free polygon areas, bottom side:
890  if( freeArea.OutlineCount() > 0 )
891  {
892  m_overlay->SetFillColor( COLOR4D(0.0, 0.7, 0.0, 0.2) );
893  m_overlay->Polygon( freeArea );
894  }
895 }
SHAPE_POLY_SET m_topFreeArea
int OutlineCount() const
Returns the number of outlines in the set
Class SHAPE_POLY_SET.
SHAPE_POLY_SET m_bottomFreeArea
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
std::shared_ptr< KIGFX::VIEW_OVERLAY > m_overlay
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
bool AR_AUTOPLACER::fillMatrix ( )
private

fills m_matrix cells from m_boardShape.

cells inside m_boardShape are set to CELL_IS_ZONE

Definition at line 156 of file ar_autoplacer.cpp.

References AR_SIDE_BOTTOM, SHAPE_LINE_CHAIN::BBox(), CELL_IS_ZONE, SHAPE_LINE_CHAIN::CPoint(), SHAPE_POLY_SET::Fracture(), BOX2< Vec >::GetBottom(), AR_MATRIX::GetBrdCoordOrigin(), BOX2< Vec >::GetY(), m_boardShape, AR_MATRIX::m_GridRouting, m_matrix, AR_MATRIX::m_Ncols, AR_MATRIX::m_Nrows, SHAPE_POLY_SET::Outline(), SHAPE_POLY_SET::PM_FAST, SHAPE_LINE_CHAIN::PointCount(), AR_MATRIX::SetCell(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by genPlacementRoutingMatrix(), and SetProgressReporter().

157 {
158  std::vector <int> x_coordinates;
159  bool success = true;
160  int step = m_matrix.m_GridRouting;
161  wxPoint coord_orgin = m_matrix.GetBrdCoordOrigin(); // Board coordinate of matruix cell (0,0)
162 
163  // Create a single board outline:
164  SHAPE_POLY_SET brd_shape = m_boardShape;
165  brd_shape.Fracture( SHAPE_POLY_SET::PM_FAST );
166  const SHAPE_LINE_CHAIN& outline = brd_shape.Outline(0);
167  const BOX2I& rect = outline.BBox();
168 
169  // Creates the horizontal segments
170  // Calculate the y limits of the area
171  for( int refy = rect.GetY(), endy = rect.GetBottom(); refy < endy; refy += step )
172  {
173  // The row index (vertical position) of current line scan inside the placement matrix
174  int idy = (refy - coord_orgin.y) / step;
175 
176  // Ensure we are still inside the placement matrix
177  if( idy >= m_matrix.m_Nrows )
178  break;
179 
180  // Ensure we are inside the placement matrix
181  if( idy <= 0 )
182  continue;
183 
184  // find all intersection points of an infinite line with polyline sides
185  x_coordinates.clear();
186 
187  for( int v = 0; v < outline.PointCount(); v++ )
188  {
189 
190  int seg_startX = outline.CPoint( v ).x;
191  int seg_startY = outline.CPoint( v ).y;
192  int seg_endX = outline.CPoint( v + 1 ).x;
193  int seg_endY = outline.CPoint( v + 1 ).y;
194 
195  /* Trivial cases: skip if ref above or below the segment to test */
196  if( ( seg_startY > refy ) && ( seg_endY > refy ) )
197  continue;
198 
199  // segment below ref point, or its Y end pos on Y coordinate ref point: skip
200  if( ( seg_startY <= refy ) && (seg_endY <= refy ) )
201  continue;
202 
203  /* at this point refy is between seg_startY and seg_endY
204  * see if an horizontal line at Y = refy is intersecting this segment
205  */
206  // calculate the x position of the intersection of this segment and the
207  // infinite line this is more easier if we move the X,Y axis origin to
208  // the segment start point:
209 
210  seg_endX -= seg_startX;
211  seg_endY -= seg_startY;
212  double newrefy = (double) ( refy - seg_startY );
213  double intersec_x;
214 
215  if ( seg_endY == 0 ) // horizontal segment on the same line: skip
216  continue;
217 
218  // Now calculate the x intersection coordinate of the horizontal line at
219  // y = newrefy and the segment from (0,0) to (seg_endX,seg_endY) with the
220  // horizontal line at the new refy position the line slope is:
221  // slope = seg_endY/seg_endX; and inv_slope = seg_endX/seg_endY
222  // and the x pos relative to the new origin is:
223  // intersec_x = refy/slope = refy * inv_slope
224  // Note: because horizontal segments are already tested and skipped, slope
225  // exists (seg_end_y not O)
226  double inv_slope = (double) seg_endX / seg_endY;
227  intersec_x = newrefy * inv_slope;
228  x_coordinates.push_back( (int) intersec_x + seg_startX );
229  }
230 
231  // A line scan is finished: build list of segments
232 
233  // Sort intersection points by increasing x value:
234  // So 2 consecutive points are the ends of a segment
235  std::sort( x_coordinates.begin(), x_coordinates.end() );
236 
237  // An even number of coordinates is expected, because a segment has 2 ends.
238  // An if this algorithm always works, it must always find an even count.
239  if( ( x_coordinates.size() & 1 ) != 0 )
240  {
241  success = false;
242  break;
243  }
244 
245  // Fill cells having the same Y coordinate
246  int iimax = x_coordinates.size() - 1;
247 
248  for( int ii = 0; ii < iimax; ii += 2 )
249  {
250  int seg_start_x = x_coordinates[ii] - coord_orgin.x;
251  int seg_end_x = x_coordinates[ii + 1] - coord_orgin.x;
252  // Fill cells at y coord = idy,
253  // and at x cood >= seg_start_x and <= seg_end_x
254 
255  for( int idx = seg_start_x / step; idx < m_matrix.m_Ncols; idx++ )
256  {
257  if( idx * step > seg_end_x )
258  break;
259 
260  if( idx * step >= seg_start_x )
262  }
263 
264  }
265  } // End examine segments in one area
266 
267  return success;
268 }
#define AR_SIDE_BOTTOM
Definition: ar_matrix.h:43
coord_type GetY() const
Definition: box2.h:189
int m_Ncols
Definition: ar_matrix.h:65
int PointCount() const
Function PointCount()
int m_GridRouting
Definition: ar_matrix.h:63
#define CELL_IS_ZONE
Definition: ar_cell.h:40
AR_MATRIX m_matrix
const BOX2I BBox(int aClearance=0) const override
Function BBox()
SHAPE_POLY_SET m_boardShape
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
coord_type GetBottom() const
Definition: box2.h:198
int m_Nrows
Definition: ar_matrix.h:65
void SetCell(int aRow, int aCol, int aSide, MATRIX_CELL aCell)
Definition: ar_matrix.cpp:205
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
Class SHAPE_LINE_CHAIN.
wxPoint GetBrdCoordOrigin()
function GetBrdCoordOrigin
Definition: ar_matrix.h:99
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
void AR_AUTOPLACER::genModuleOnRoutingMatrix ( MODULE Module)
private

Definition at line 368 of file ar_autoplacer.cpp.

References AR_GAIN, AR_KEEPOUT_MARGIN, B_Cu, SHAPE_POLY_SET::BooleanSubtract(), buildFpAreas(), CELL_IS_MODULE, AR_MATRIX::CreateKeepOutRectangle(), F_Cu, EDA_RECT::GetBottom(), MODULE::GetBoundingBox(), BOARD_ITEM::GetLayer(), MODULE::GetPadCount(), EDA_RECT::GetRight(), EDA_RECT::GetX(), EDA_RECT::GetY(), EDA_RECT::Inflate(), m_bottomFreeArea, AR_MATRIX::m_BrdBox, m_fpAreaBottom, m_fpAreaTop, AR_MATRIX::m_GridRouting, m_matrix, m_topFreeArea, MODULE::Pads(), AR_MATRIX::PlacePad(), SHAPE_POLY_SET::PM_FAST, AR_MATRIX::TraceFilledRectangle(), and AR_MATRIX::WRITE_OR_CELL.

Referenced by AutoplaceModules(), and SetProgressReporter().

369 {
370  int ox, oy, fx, fy;
371  LSET layerMask;
372  EDA_RECT fpBBox = Module->GetBoundingBox();
373 
374  fpBBox.Inflate( m_matrix.m_GridRouting / 2 );
375  ox = fpBBox.GetX();
376  fx = fpBBox.GetRight();
377  oy = fpBBox.GetY();
378  fy = fpBBox.GetBottom();
379 
380  if( ox < m_matrix.m_BrdBox.GetX() )
381  ox = m_matrix.m_BrdBox.GetX();
382 
383  if( ox > m_matrix.m_BrdBox.GetRight() )
384  ox = m_matrix.m_BrdBox.GetRight();
385 
386  if( fx < m_matrix.m_BrdBox.GetX() )
387  fx = m_matrix.m_BrdBox.GetX();
388 
389  if( fx > m_matrix.m_BrdBox.GetRight() )
390  fx = m_matrix.m_BrdBox.GetRight();
391 
392  if( oy < m_matrix.m_BrdBox.GetY() )
393  oy = m_matrix.m_BrdBox.GetY();
394 
395  if( oy > m_matrix.m_BrdBox.GetBottom() )
396  oy = m_matrix.m_BrdBox.GetBottom();
397 
398  if( fy < m_matrix.m_BrdBox.GetY() )
399  fy = m_matrix.m_BrdBox.GetY();
400 
401  if( fy > m_matrix.m_BrdBox.GetBottom() )
402  fy = m_matrix.m_BrdBox.GetBottom();
403 
404  if( Module->GetLayer() == F_Cu )
405  layerMask.set( F_Cu );
406 
407  if( Module->GetLayer() == B_Cu )
408  layerMask.set( B_Cu );
409 
410  m_matrix.TraceFilledRectangle( ox, oy, fx, fy, layerMask,
412 
413  // Trace pads + clearance areas.
414  for( auto pad : Module->Pads() )
415  {
416  int margin = (m_matrix.m_GridRouting / 2) + pad->GetClearance();
418  }
419 
420  // Trace clearance.
421  int margin = ( m_matrix.m_GridRouting * Module->GetPadCount() ) / AR_GAIN;
422  m_matrix.CreateKeepOutRectangle( ox, oy, fx, fy, margin, AR_KEEPOUT_MARGIN , layerMask );
423 
424  // Build the footprint courtyard
425  buildFpAreas( Module, margin );
426 
427  // Substract the shape to free areas
430 }
SHAPE_POLY_SET m_topFreeArea
#define CELL_IS_MODULE
Definition: ar_cell.h:37
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int m_GridRouting
Definition: ar_matrix.h:63
void TraceFilledRectangle(int ux0, int uy0, int ux1, int uy1, double angle, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:794
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:168
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...
Definition: ar_matrix.cpp:1175
void PlacePad(D_PAD *aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:1280
void buildFpAreas(MODULE *aFootprint, int aFpClearance)
#define AR_GAIN
#define AR_KEEPOUT_MARGIN
AR_MATRIX m_matrix
SHAPE_POLY_SET m_fpAreaBottom
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
Class LSET is a set of PCB_LAYER_IDs.
SHAPE_POLY_SET m_bottomFreeArea
int GetBottom() const
Definition: eda_rect.h:122
SHAPE_POLY_SET m_fpAreaTop
int GetRight() const
Definition: eda_rect.h:119
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetX() const
Definition: eda_rect.h:109
int GetY() const
Definition: eda_rect.h:110
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp ...
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int AR_AUTOPLACER::genPlacementRoutingMatrix ( )
private

Definition at line 103 of file ar_autoplacer.cpp.

References AR_SIDE_BOTTOM, AR_SIDE_TOP, B_Cu, CELL_IS_EDGE, CELL_IS_HOLE, AR_MATRIX::ComputeMatrixSize(), BOARD::Drawings(), Edge_Cuts, F_Cu, fillMatrix(), BOARD::GetBoardEdgesBoundingBox(), BOARD::GetBoardPolygonOutlines(), EDA_RECT::GetHeight(), EDA_RECT::GetWidth(), AR_MATRIX::InitRoutingMatrix(), m_board, m_boardShape, AR_MATRIX::m_BoardSide, m_bottomFreeArea, AR_MATRIX::m_GridRouting, m_matrix, AR_MATRIX::m_Ncols, AR_MATRIX::m_Nrows, AR_MATRIX::m_routeLayerBottom, AR_MATRIX::m_routeLayerTop, AR_MATRIX::m_RoutingLayersCount, m_topFreeArea, PCB_LINE_T, AR_MATRIX::TraceSegmentPcb(), AR_MATRIX::UnInitRoutingMatrix(), and AR_MATRIX::WRITE_CELL.

Referenced by AutoplaceModules(), and SetProgressReporter().

104 {
106 
108 
109  if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
110  return 0;
111 
112  // Build the board shape
113  m_board->GetBoardPolygonOutlines( m_boardShape /*, aErrorText, aErrorLocation*/ );
116 
117  m_matrix.ComputeMatrixSize( bbox );
118  int nbCells = m_matrix.m_Ncols * m_matrix.m_Nrows;
119 
120  // Choose the number of board sides.
125 
126  // Fill (mark) the cells inside the board:
127  fillMatrix();
128 
129  // Other obstacles can be added here:
130  for( auto drawing : m_board->Drawings() )
131  {
132  switch( drawing->Type() )
133  {
134  case PCB_LINE_T:
135  if( drawing->GetLayer() != Edge_Cuts )
136  {
139  }
140  break;
141 
142  default:
143  break;
144  }
145  }
146 
147  // Initialize top layer. to the same value as the bottom layer
150  nbCells * sizeof(AR_MATRIX::MATRIX_CELL) );
151 
152  return 1;
153 }
SHAPE_POLY_SET m_topFreeArea
#define AR_SIDE_BOTTOM
Definition: ar_matrix.h:43
int InitRoutingMatrix()
Function InitBoard initializes the data structures.
Definition: ar_matrix.cpp:92
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
int m_Ncols
Definition: ar_matrix.h:65
int m_GridRouting
Definition: ar_matrix.h:63
int GetHeight() const
Definition: eda_rect.h:118
void TraceSegmentPcb(DRAWSEGMENT *pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:1085
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:810
AR_MATRIX m_matrix
PCB_LAYER_ID m_routeLayerTop
Definition: ar_matrix.h:69
SHAPE_POLY_SET m_boardShape
#define CELL_IS_HOLE
Definition: ar_cell.h:36
int m_Nrows
Definition: ar_matrix.h:65
MATRIX_CELL * m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:56
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines...
SHAPE_POLY_SET m_bottomFreeArea
bool fillMatrix()
fills m_matrix cells from m_boardShape.
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:140
int m_RoutingLayersCount
Definition: ar_matrix.h:62
#define CELL_IS_EDGE
Definition: ar_cell.h:38
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetWidth() const
Definition: eda_rect.h:117
unsigned char MATRIX_CELL
Definition: ar_matrix.h:52
bool ComputeMatrixSize(const EDA_RECT &aBoundingBox)
Function ComputeMatrixSize calculates the number of rows and columns of dimensions of aPcb for routin...
Definition: ar_matrix.cpp:62
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
PCB_LAYER_ID m_routeLayerBottom
Definition: ar_matrix.h:70
int AR_AUTOPLACER::getOptimalModulePlacement ( MODULE aModule)
private

Definition at line 602 of file ar_autoplacer.cpp.

References B_Cu, MODULE::CalculateBoundingBox(), computePlacementRatsnestCost(), F_Cu, EDA_RECT::GetEnd(), MODULE::GetFootprintRect(), BOARD_ITEM::GetLayer(), EDA_RECT::GetOrigin(), MODULE::GetPosition(), AR_MATRIX::m_BrdBox, m_curPosition, AR_MATRIX::m_GridRouting, m_matrix, m_minCost, AR_MATRIX::m_RoutingLayersCount, EDA_RECT::Move(), MODULE::Pads(), EDA_RECT::SetOrigin(), and testModuleOnBoard().

Referenced by AutoplaceModules(), and SetProgressReporter().

603 {
604  int error = 1;
605  wxPoint LastPosOK;
606  double min_cost, curr_cost, Score;
607  bool TstOtherSide;
608 
609  aModule->CalculateBoundingBox();
610 
611  LastPosOK = m_matrix.m_BrdBox.GetOrigin();
612 
613  wxPoint mod_pos = aModule->GetPosition();
614  EDA_RECT fpBBox = aModule->GetFootprintRect();
615 
616  // Move fpBBox to have the footprint position at (0,0)
617  fpBBox.Move( -mod_pos );
618  wxPoint fpBBoxOrg = fpBBox.GetOrigin();
619 
620  // Calculate the limit of the footprint position, relative
621  // to the routing matrix area
622  wxPoint xylimit = m_matrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
623 
624  wxPoint initialPos = m_matrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
625 
626  // Stay on grid.
627  initialPos.x -= initialPos.x % m_matrix.m_GridRouting;
628  initialPos.y -= initialPos.y % m_matrix.m_GridRouting;
629 
630  m_curPosition = initialPos;
631  auto moduleOffset = mod_pos - m_curPosition;
632 
633  /* Examine pads, and set TstOtherSide to true if a footprint
634  * has at least 1 pad through.
635  */
636  TstOtherSide = false;
637 
639  {
640  LSET other( aModule->GetLayer() == B_Cu ? F_Cu : B_Cu );
641 
642  for( auto pad : aModule->Pads() )
643  {
644  if( !( pad->GetLayerSet() & other ).any() )
645  continue;
646 
647  TstOtherSide = true;
648  break;
649  }
650  }
651 
652  fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
653 
654  min_cost = -1.0;
655 // m_frame->SetStatusText( wxT( "Score ??, pos ??" ) );
656 
657 
658  for( ; m_curPosition.x < xylimit.x; m_curPosition.x += m_matrix.m_GridRouting )
659  {
660  m_curPosition.y = initialPos.y;
661 
662  for( ; m_curPosition.y < xylimit.y; m_curPosition.y += m_matrix.m_GridRouting )
663  {
664 
665  fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
666  moduleOffset = mod_pos - m_curPosition;
667  int keepOutCost = testModuleOnBoard( aModule, TstOtherSide, moduleOffset );
668 
669  if( keepOutCost >= 0 ) // i.e. if the module can be put here
670  {
671  error = 0;
672  // m_frame->build_ratsnest_module( aModule ); // fixme
673  curr_cost = computePlacementRatsnestCost( aModule, moduleOffset );
674  Score = curr_cost + keepOutCost;
675 
676  if( (min_cost >= Score ) || (min_cost < 0 ) )
677  {
678  LastPosOK = m_curPosition;
679  min_cost = Score;
680  wxString msg;
681 /* msg.Printf( wxT( "Score %g, pos %s, %s" ),
682  min_cost,
683  GetChars( ::CoordinateToString( LastPosOK.x ) ),
684  GetChars( ::CoordinateToString( LastPosOK.y ) ) );
685  m_frame->SetStatusText( msg );*/
686  }
687  }
688  }
689  }
690 
691  // Regeneration of the modified variable.
692  m_curPosition = LastPosOK;
693 
694  m_minCost = min_cost;
695  return error;
696 }
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
int m_GridRouting
Definition: ar_matrix.h:63
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
DLIST_ITERATOR_WRAPPER< D_PAD > Pads()
Definition: class_module.h:168
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:124
AR_MATRIX m_matrix
Class LSET is a set of PCB_LAYER_IDs.
double computePlacementRatsnestCost(MODULE *aModule, const wxPoint &aOffset)
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text...
int testModuleOnBoard(MODULE *aModule, bool TstOtherSide, const wxPoint &aOffset)
const wxPoint GetEnd() const
Definition: eda_rect.h:114
int m_RoutingLayersCount
Definition: ar_matrix.h:62
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
wxPoint m_curPosition
const wxPoint GetPosition() const override
Definition: class_module.h:183
const D_PAD * AR_AUTOPLACER::nearestPad ( MODULE aRefModule,
D_PAD aRefPad,
const wxPoint &  aOffset 
)
private

Definition at line 699 of file ar_autoplacer.cpp.

References EDA_RECT::Contains(), dist, BOARD_CONNECTED_ITEM::GetNetCode(), D_PAD::GetPosition(), m_board, AR_MATRIX::m_BrdBox, m_matrix, mod, and BOARD::Modules().

Referenced by computePlacementRatsnestCost(), and SetProgressReporter().

700 {
701  const D_PAD* nearest = nullptr;
702  int64_t nearestDist = INT64_MAX;
703 
704  for ( auto mod : m_board->Modules() )
705  {
706  if ( mod == aRefModule )
707  continue;
708 
709  if( !m_matrix.m_BrdBox.Contains( mod->GetPosition() ) )
710  continue;
711 
712  for ( auto pad: mod->Pads() )
713  {
714  if ( pad->GetNetCode() != aRefPad->GetNetCode() || pad->GetNetCode() <= 0 )
715  continue;
716 
717  auto dist = (VECTOR2I( aRefPad->GetPosition() - aOffset ) - VECTOR2I( pad->GetPosition() ) ).EuclideanNorm();
718 
719  if ( dist < nearestDist )
720  {
721  nearestDist = dist;
722  nearest = pad;
723  }
724  }
725  }
726 
727  return nearest;
728 }
static const int dist[10][10]
Definition: ar_matrix.cpp:320
bool Contains(const wxPoint &aPoint) const
Function Contains.
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
AR_MATRIX m_matrix
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
int GetNetCode() const
Function GetNetCode.
const wxPoint GetPosition() const override
Definition: class_pad.h:220
#define mod(a, n)
Definition: greymap.cpp:24
MODULE * AR_AUTOPLACER::pickModule ( )
private

Find the "best" module place.

The criteria are:

  • Maximum ratsnest with modules already placed
  • Max size, and number of pads max

Definition at line 802 of file ar_autoplacer.cpp.

References MODULE::CalculateBoundingBox(), MODULE::GetFlag(), m_board, m_connectivity, BOARD::Modules(), MODULE::NeedsPlaced(), MODULE::SetFlag(), sortFootprintsByComplexity(), and sortFootprintsByRatsnestSize().

Referenced by AutoplaceModules(), and SetProgressReporter().

803 {
804  MODULE* module;
805  std::vector <MODULE*> moduleList;
806 
807 
808  for( auto m : m_board->Modules() )
809  {
811  moduleList.push_back( m );
812  }
813 
814  sort( moduleList.begin(), moduleList.end(), sortFootprintsByComplexity );
815 
816  for( unsigned kk = 0; kk < moduleList.size(); kk++ )
817  {
818  module = moduleList[kk];
819  module->SetFlag( 0 );
820 
821  if( !module->NeedsPlaced() )
822  continue;
823 
824  m_connectivity->Update( module );
825  }
826 
827  m_connectivity->RecalculateRatsnest();
828 
829  for( unsigned kk = 0; kk < moduleList.size(); kk++ )
830  {
831  module = moduleList[kk];
832 
833  auto edges = m_connectivity->GetRatsnestForComponent( module, true );
834 
835  module->SetFlag( edges.size() ) ;
836  }
837 
838  sort( moduleList.begin(), moduleList.end(), sortFootprintsByRatsnestSize );
839 
840  // Search for "best" module.
841  MODULE* bestModule = nullptr;
842  MODULE* altModule = nullptr;
843 
844  for( unsigned ii = 0; ii < moduleList.size(); ii++ )
845  {
846  module = moduleList[ii];
847 
848  if( !module->NeedsPlaced() )
849  continue;
850 
851  altModule = module;
852 
853  if( module->GetFlag() == 0 )
854  continue;
855 
856  bestModule = module;
857  break;
858  }
859 
860  if( bestModule )
861  return bestModule;
862  else
863  return altModule;
864 }
int GetFlag() const
Definition: class_module.h:230
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
bool NeedsPlaced() const
Definition: class_module.h:294
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
static bool sortFootprintsByComplexity(MODULE *ref, MODULE *compare)
static bool sortFootprintsByRatsnestSize(MODULE *ref, MODULE *compare)
void SetFlag(int aFlag)
Definition: class_module.h:228
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity
void AR_AUTOPLACER::placeModule ( MODULE aModule,
bool  aDoNotRecreateRatsnest,
const wxPoint &  aPos 
)
private

Definition at line 93 of file ar_autoplacer.cpp.

References m_connectivity, and MODULE::SetPosition().

Referenced by AutoplaceModules(), and SetProgressReporter().

94 {
95  if( !aModule )
96  return;
97 
98  aModule->SetPosition( aPos );
99  m_connectivity->Update( aModule );
100 }
void SetPosition(const wxPoint &aPos) override
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity
const std::vector<MODULE*> AR_AUTOPLACER::QueryOffboardModules ( )
void AR_AUTOPLACER::rotateModule ( MODULE module,
double  angle,
bool  incremental 
)
private

Definition at line 272 of file ar_autoplacer.cpp.

References PNS::angle(), BOARD::GetConnectivity(), MODULE::GetOrientation(), m_board, and MODULE::SetOrientation().

Referenced by AutoplaceModules(), and SetProgressReporter().

273 {
274  if( module == NULL )
275  return;
276 
277  if( incremental )
278  module->SetOrientation( module->GetOrientation() + angle );
279  else
280  module->SetOrientation( angle );
281 
282 
283  m_board->GetConnectivity()->Update( module );
284 }
double GetOrientation() const
Definition: class_module.h:188
void SetOrientation(double newangle)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
void AR_AUTOPLACER::SetOverlay ( std::shared_ptr< KIGFX::VIEW_OVERLAY aOverlay)
inline

Set a VIEW overlay to draw items during a autoplace session.

Definition at line 76 of file ar_autoplacer.h.

References m_overlay.

Referenced by AUTOPLACE_TOOL::autoplace().

77  {
78  m_overlay = aOverlay;
79  }
std::shared_ptr< KIGFX::VIEW_OVERLAY > m_overlay
void AR_AUTOPLACER::SetPlacementGrid ( int  aGrid)
inline

Definition at line 68 of file ar_autoplacer.h.

References m_gridSize.

69  {
70  m_gridSize = aGrid;
71  }
void AR_AUTOPLACER::SetRefreshCallback ( std::function< int(MODULE *aModule)>  aCallback)
inline

a callback function to redraw on screen the view after changes, for instance after moving a footprint

Definition at line 85 of file ar_autoplacer.h.

References m_refreshCallback.

Referenced by AUTOPLACE_TOOL::autoplace().

86  {
87  m_refreshCallback = aCallback;
88  }
std::function< int(MODULE *aModule)> m_refreshCallback
int AR_AUTOPLACER::testModuleByPolygon ( MODULE aModule,
int  aSide,
const wxPoint &  aOffset 
)
private

Definition at line 491 of file ar_autoplacer.cpp.

References AR_FREE_CELL, AR_OCCUIPED_BY_MODULE, SHAPE_POLY_SET::BooleanSubtract(), m_fpAreaTop, m_topFreeArea, SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::OutlineCount(), and SHAPE_POLY_SET::PM_FAST.

Referenced by SetProgressReporter().

492 {
493  // Test for footprint out of board:
494  // If a footprint is not fully inside the board, substract board polygon
495  // to the footprint polygon gives a non null area.
496  SHAPE_POLY_SET fp_area = m_fpAreaTop;
497  fp_area.Move( -aOffset );
498  SHAPE_POLY_SET out_of_board_area;
499  out_of_board_area.BooleanSubtract( fp_area, m_topFreeArea, SHAPE_POLY_SET::PM_FAST );
500 
501  if( out_of_board_area.OutlineCount() )
502  return AR_OCCUIPED_BY_MODULE;
503 
504  return AR_FREE_CELL;
505 }
SHAPE_POLY_SET m_topFreeArea
int OutlineCount() const
Returns the number of outlines in the set
void Move(const VECTOR2I &aVector) override
Class SHAPE_POLY_SET.
SHAPE_POLY_SET m_fpAreaTop
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp ...
int AR_AUTOPLACER::testModuleOnBoard ( MODULE aModule,
bool  TstOtherSide,
const wxPoint &  aOffset 
)
private

Definition at line 565 of file ar_autoplacer.cpp.

References AR_FREE_CELL, AR_GAIN, AR_SIDE_BOTTOM, AR_SIDE_TOP, B_Cu, buildFpAreas(), calculateKeepOutArea(), MODULE::GetFootprintRect(), BOARD_ITEM::GetLayer(), MODULE::GetPadCount(), EDA_RECT::Inflate(), AR_MATRIX::m_GridRouting, m_matrix, EDA_RECT::Move(), and testRectangle().

Referenced by getOptimalModulePlacement(), and SetProgressReporter().

566 {
567  int side = AR_SIDE_TOP;
568  int otherside = AR_SIDE_BOTTOM;
569 
570  if( aModule->GetLayer() == B_Cu )
571  {
572  side = AR_SIDE_BOTTOM; otherside = AR_SIDE_TOP;
573  }
574 
575  EDA_RECT fpBBox = aModule->GetFootprintRect();
576  fpBBox.Move( -aOffset );
577 
578  buildFpAreas( aModule, 0 );
579 
580  int diag = //testModuleByPolygon( aModule, side, aOffset );
581  testRectangle( fpBBox, side );
582 //printf("test %p diag %d\n", aModule, diag);fflush(0);
583  if( diag != AR_FREE_CELL )
584  return diag;
585 
586  if( TstOtherSide )
587  {
588  diag = //testModuleByPolygon( aModule, otherside, aOffset );
589  testRectangle( fpBBox, otherside );
590 
591  if( diag != AR_FREE_CELL )
592  return diag;
593  }
594 
595  int marge = ( m_matrix.m_GridRouting * aModule->GetPadCount() ) / AR_GAIN;
596 
597  fpBBox.Inflate( marge );
598  return calculateKeepOutArea( fpBBox, side );
599 }
#define AR_SIDE_BOTTOM
Definition: ar_matrix.h:43
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int m_GridRouting
Definition: ar_matrix.h:63
void buildFpAreas(MODULE *aFootprint, int aFpClearance)
#define AR_GAIN
AR_MATRIX m_matrix
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text...
unsigned int calculateKeepOutArea(const EDA_RECT &aRect, int side)
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
int testRectangle(const EDA_RECT &aRect, int side)
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int AR_AUTOPLACER::testRectangle ( const EDA_RECT aRect,
int  side 
)
private

Definition at line 439 of file ar_autoplacer.cpp.

References AR_FREE_CELL, AR_OCCUIPED_BY_MODULE, AR_OUT_OF_BOARD, CELL_IS_MODULE, CELL_IS_ZONE, AR_MATRIX::GetCell(), EDA_RECT::GetEnd(), EDA_RECT::GetOrigin(), EDA_RECT::Inflate(), AR_MATRIX::m_BrdBox, AR_MATRIX::m_GridRouting, m_matrix, AR_MATRIX::m_Ncols, and AR_MATRIX::m_Nrows.

Referenced by SetProgressReporter(), and testModuleOnBoard().

440 {
441  EDA_RECT rect = aRect;
442 
443  rect.Inflate( m_matrix.m_GridRouting / 2 );
444 
445  wxPoint start = rect.GetOrigin();
446  wxPoint end = rect.GetEnd();
447 
448  start -= m_matrix.m_BrdBox.GetOrigin();
449  end -= m_matrix.m_BrdBox.GetOrigin();
450 
451  int row_min = start.y / m_matrix.m_GridRouting;
452  int row_max = end.y / m_matrix.m_GridRouting;
453  int col_min = start.x / m_matrix.m_GridRouting;
454  int col_max = end.x / m_matrix.m_GridRouting;
455 
456  if( start.y > row_min * m_matrix.m_GridRouting )
457  row_min++;
458 
459  if( start.x > col_min * m_matrix.m_GridRouting )
460  col_min++;
461 
462  if( row_min < 0 )
463  row_min = 0;
464 
465  if( row_max >= ( m_matrix.m_Nrows - 1 ) )
466  row_max = m_matrix.m_Nrows - 1;
467 
468  if( col_min < 0 )
469  col_min = 0;
470 
471  if( col_max >= ( m_matrix.m_Ncols - 1 ) )
472  col_max = m_matrix.m_Ncols - 1;
473 
474  for( int row = row_min; row <= row_max; row++ )
475  {
476  for( int col = col_min; col <= col_max; col++ )
477  {
478  unsigned int data = m_matrix.GetCell( row, col, side );
479 
480  if( ( data & CELL_IS_ZONE ) == 0 )
481  return AR_OUT_OF_BOARD;
482 
483  if( (data & CELL_IS_MODULE) )
484  return AR_OCCUIPED_BY_MODULE;
485  }
486  }
487 
488  return AR_FREE_CELL;
489 }
const wxPoint GetOrigin() const
Definition: eda_rect.h:112
int m_Ncols
Definition: ar_matrix.h:65
#define CELL_IS_MODULE
Definition: ar_cell.h:37
int m_GridRouting
Definition: ar_matrix.h:63
#define CELL_IS_ZONE
Definition: ar_cell.h:40
EDA_RECT m_BrdBox
Definition: ar_matrix.h:64
AR_MATRIX m_matrix
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:194
int m_Nrows
Definition: ar_matrix.h:65
const wxPoint GetEnd() const
Definition: eda_rect.h:114
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.

Member Data Documentation

BOARD* AR_AUTOPLACER::m_board
private
SHAPE_POLY_SET AR_AUTOPLACER::m_boardShape
private

Definition at line 136 of file ar_autoplacer.h.

Referenced by fillMatrix(), and genPlacementRoutingMatrix().

SHAPE_POLY_SET AR_AUTOPLACER::m_bottomFreeArea
private
std::unique_ptr<CONNECTIVITY_DATA> AR_AUTOPLACER::m_connectivity
private

Definition at line 148 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), pickModule(), and placeModule().

wxPoint AR_AUTOPLACER::m_curPosition
private

Definition at line 142 of file ar_autoplacer.h.

Referenced by AutoplaceModules(), and getOptimalModulePlacement().

SHAPE_POLY_SET AR_AUTOPLACER::m_fpAreaBottom
private

Definition at line 138 of file ar_autoplacer.h.

Referenced by addFpBody(), addPad(), buildFpAreas(), and genModuleOnRoutingMatrix().

SHAPE_POLY_SET AR_AUTOPLACER::m_fpAreaTop
private
int AR_AUTOPLACER::m_gridSize
private

Definition at line 145 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), AutoplaceModules(), and SetPlacementGrid().

double AR_AUTOPLACER::m_minCost
private

Definition at line 144 of file ar_autoplacer.h.

Referenced by AutoplaceModules(), and getOptimalModulePlacement().

wxPoint AR_AUTOPLACER::m_moduleOffset
private

Definition at line 143 of file ar_autoplacer.h.

std::shared_ptr<KIGFX::VIEW_OVERLAY> AR_AUTOPLACER::m_overlay
private

Definition at line 147 of file ar_autoplacer.h.

Referenced by drawPlacementRoutingMatrix(), and SetOverlay().

PROGRESS_REPORTER* AR_AUTOPLACER::m_progressReporter
private

Definition at line 150 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), AutoplaceModules(), and SetProgressReporter().

std::function<int( MODULE* aModule )> AR_AUTOPLACER::m_refreshCallback
private

Definition at line 149 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), AutoplaceModules(), and SetRefreshCallback().

SHAPE_POLY_SET AR_AUTOPLACER::m_topFreeArea
private

The documentation for this class was generated from the following files: