KiCad PCB EDA Suite
AR_AUTOPLACER Class Reference

#include <ar_autoplacer.h>

Public Member Functions

 AR_AUTOPLACER (BOARD *aBoard)
 
AR_RESULT AutoplaceFootprints (std::vector< FOOTPRINT * > &aFootprints, BOARD_COMMIT *aCommit, bool aPlaceOffboardModules=false)
 
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(FOOTPRINT *aFootprint)> 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 rotateFootprint (FOOTPRINT *aFootprint, double angle, bool incremental)
 
int genPlacementRoutingMatrix ()
 
bool fillMatrix ()
 fills m_matrix cells from m_boardShape. More...
 
void genModuleOnRoutingMatrix (FOOTPRINT *aFootprint)
 
int testRectangle (const EDA_RECT &aRect, int side)
 
unsigned int calculateKeepOutArea (const EDA_RECT &aRect, int side)
 
int testFootprintOnBoard (FOOTPRINT *aFootprint, bool TstOtherSide, const wxPoint &aOffset)
 
int getOptimalFPPlacement (FOOTPRINT *aFootprint)
 
double computePlacementRatsnestCost (FOOTPRINT *aFootprint, const wxPoint &aOffset)
 
FOOTPRINTpickFootprint ()
 Find the "best" footprint place. More...
 
void placeFootprint (FOOTPRINT *aFootprint, bool aDoNotRecreateRatsnest, const wxPoint &aPos)
 
const PADnearestPad (FOOTPRINT *aRefFP, PAD *aRefPad, const wxPoint &aOffset)
 
void addFpBody (wxPoint aStart, wxPoint aEnd, LSET aLayerMask)
 
void addPad (PAD *aPad, int aClearance)
 
void buildFpAreas (FOOTPRINT *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
 
double m_minCost
 
int m_gridSize
 
std::shared_ptr< KIGFX::VIEW_OVERLAYm_overlay
 
std::unique_ptr< CONNECTIVITY_DATAm_connectivity
 
std::function< int(FOOTPRINT *aFootprint)> m_refreshCallback
 
PROGRESS_REPORTERm_progressReporter
 

Detailed Description

Definition at line 57 of file ar_autoplacer.h.

Constructor & Destructor Documentation

◆ AR_AUTOPLACER()

AR_AUTOPLACER::AR_AUTOPLACER ( BOARD aBoard)

Definition at line 80 of file ar_autoplacer.cpp.

81 {
82  m_board = aBoard;
83  m_connectivity = std::make_unique<CONNECTIVITY_DATA>( );
84 
85  for( FOOTPRINT* footprint : m_board->Footprints() )
86  m_connectivity->Add( footprint );
87 
89  m_progressReporter = nullptr;
90  m_refreshCallback = nullptr;
91  m_minCost = 0.0;
92 }
PROGRESS_REPORTER * m_progressReporter
FOOTPRINTS & Footprints()
Definition: board.h:283
#define STEP_AR_MM
static constexpr int Millimeter2iu(double mm)
std::function< int(FOOTPRINT *aFootprint)> m_refreshCallback
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity

References BOARD::Footprints(), m_board, m_connectivity, m_gridSize, m_minCost, m_progressReporter, m_refreshCallback, Millimeter2iu(), and STEP_AR_MM.

Member Function Documentation

◆ addFpBody()

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

Definition at line 289 of file ar_autoplacer.cpp.

290 {
291  // Add a polygonal shape (rectangle) to m_fpAreaFront and/or m_fpAreaBack
292  if( aLayerMask[ F_Cu ] )
293  {
295  m_fpAreaTop.Append( aStart.x, aStart.y );
296  m_fpAreaTop.Append( aEnd.x, aStart.y );
297  m_fpAreaTop.Append( aEnd.x, aEnd.y );
298  m_fpAreaTop.Append( aStart.x, aEnd.y );
299  }
300  if( aLayerMask[ B_Cu ] )
301  {
303  m_fpAreaBottom.Append( aStart.x, aStart.y );
304  m_fpAreaBottom.Append( aEnd.x, aStart.y );
305  m_fpAreaBottom.Append( aEnd.x, aEnd.y );
306  m_fpAreaBottom.Append( aStart.x, aEnd.y );
307  }
308 }
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)

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

Referenced by buildFpAreas().

◆ addPad()

void AR_AUTOPLACER::addPad ( PAD aPad,
int  aClearance 
)
private

Definition at line 310 of file ar_autoplacer.cpp.

311 {
312  // Add a polygonal shape (rectangle) to m_fpAreaFront and/or m_fpAreaBack
313  EDA_RECT bbox = aPad->GetBoundingBox();
314  bbox.Inflate( aClearance );
315 
316  if( aPad->IsOnLayer( F_Cu ) )
317  {
319  m_fpAreaTop.Append( bbox.GetLeft(), bbox.GetTop() );
320  m_fpAreaTop.Append( bbox.GetRight(), bbox.GetTop() );
321  m_fpAreaTop.Append( bbox.GetRight(), bbox.GetBottom() );
322  m_fpAreaTop.Append( bbox.GetLeft(), bbox.GetBottom() );
323  }
324  if( aPad->IsOnLayer( B_Cu ) )
325  {
327  m_fpAreaBottom.Append( bbox.GetLeft(), bbox.GetTop() );
328  m_fpAreaBottom.Append( bbox.GetRight(), bbox.GetTop() );
329  m_fpAreaBottom.Append( bbox.GetRight(), bbox.GetBottom() );
330  m_fpAreaBottom.Append( bbox.GetLeft(), bbox.GetBottom() );
331  }
332 }
int GetTop() const
Definition: eda_rect.h:123
int GetLeft() const
Definition: eda_rect.h:122
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: pad.h:544
int GetBottom() const
Definition: eda_rect.h:124
SHAPE_POLY_SET m_fpAreaBottom
int GetRight() const
Definition: eda_rect.h:121
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox The bounding box is cached, so this will be efficient most of the time.
Definition: pcbnew/pad.cpp:470
SHAPE_POLY_SET m_fpAreaTop
int NewOutline()
Creates a new empty polygon in the set and returns its index
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.
Definition: eda_rect.cpp:363
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)

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

Referenced by buildFpAreas().

◆ AutoplaceFootprints()

AR_RESULT AR_AUTOPLACER::AutoplaceFootprints ( std::vector< FOOTPRINT * > &  aFootprints,
BOARD_COMMIT aCommit,
bool  aPlaceOffboardModules = false 
)

Definition at line 877 of file ar_autoplacer.cpp.

880 {
881  wxPoint memopos;
882  int error;
883  bool cancelled = false;
884 
885  memopos = m_curPosition;
886 
887  m_matrix.m_GridRouting = m_gridSize; //(int) m_frame->GetScreen()->GetGridSize().x;
888 
889  // Ensure Board.m_GridRouting has a reasonable value:
890  if( m_matrix.m_GridRouting < Millimeter2iu( 0.25 ) )
892 
893  // Compute footprint parameters used in autoplace
894  if( genPlacementRoutingMatrix( ) == 0 )
895  return AR_FAILURE;
896 
897  int placedCount = 0;
898 
899  for( FOOTPRINT* footprint : m_board->Footprints() )
900  footprint->SetNeedsPlaced( false );
901 
902  std::vector<FOOTPRINT*> offboardMods;
903 
904  if( aPlaceOffboardModules )
905  {
906  for( FOOTPRINT* footprint : m_board->Footprints() )
907  {
908  if( !m_matrix.m_BrdBox.Contains( footprint->GetPosition() ) )
909  offboardMods.push_back( footprint );
910  }
911  }
912 
913  for( FOOTPRINT* footprint : aFootprints )
914  {
915  footprint->SetNeedsPlaced( true );
916  aCommit->Modify( footprint );
917  }
918 
919  for( FOOTPRINT* footprint : offboardMods )
920  {
921  footprint->SetNeedsPlaced( true );
922  aCommit->Modify( footprint );
923  }
924 
925  for( FOOTPRINT* footprint : m_board->Footprints() )
926  {
927  if( footprint->NeedsPlaced() ) // Erase from screen
928  placedCount++;
929  else
930  genModuleOnRoutingMatrix( footprint );
931  }
932 
933 
934  int cnt = 0;
935  wxString msg;
936 
937  if( m_progressReporter )
938  {
939  m_progressReporter->Report( _( "Autoplacing components..." ) );
940  m_progressReporter->SetMaxProgress( placedCount );
941  }
942 
944 
945  if( m_refreshCallback )
946  m_refreshCallback( nullptr );
947 
948  FOOTPRINT* footprint;
949 
950  while( ( footprint = pickFootprint() ) != nullptr )
951  {
952  // Display some info about activity, footprint placement can take a while:
953  //m_frame->SetStatusText( msg );
954 
955  if( m_progressReporter )
957  _( "Autoplacing %s" ), footprint->GetReference() ) );
958 
959  double initialOrient = footprint->GetOrientation();
960 
961  error = getOptimalFPPlacement( footprint );
962  double bestScore = m_minCost;
963  double bestRotation = 0.0;
964  int rotAllowed;
965 
966  if( error == AR_ABORT_PLACEMENT )
967  goto end_of_tst;
968 
969  // Try orientations 90, 180, 270 degrees from initial orientation
970  rotAllowed = footprint->GetPlacementCost180();
971 
972  if( rotAllowed != 0 )
973  {
974  rotateFootprint( footprint, 1800.0, true );
975  error = getOptimalFPPlacement( footprint );
976  m_minCost *= OrientationPenalty[rotAllowed];
977 
978  if( bestScore > m_minCost ) // This orientation is better.
979  {
980  bestScore = m_minCost;
981  bestRotation = 1800.0;
982  }
983  else
984  {
985  rotateFootprint( footprint, initialOrient, false );
986  }
987 
988  if( error == AR_ABORT_PLACEMENT )
989  goto end_of_tst;
990  }
991 
992  // Determine if the best orientation of a footprint is 90.
993  rotAllowed = footprint->GetPlacementCost90();
994 
995  if( rotAllowed != 0 )
996  {
997  rotateFootprint( footprint, 900.0, true );
998  error = getOptimalFPPlacement( footprint );
999  m_minCost *= OrientationPenalty[rotAllowed];
1000 
1001  if( bestScore > m_minCost ) // This orientation is better.
1002  {
1003  bestScore = m_minCost;
1004  bestRotation = 900.0;
1005  }
1006  else
1007  {
1008  rotateFootprint( footprint, initialOrient, false );
1009  }
1010 
1011  if( error == AR_ABORT_PLACEMENT )
1012  goto end_of_tst;
1013  }
1014 
1015  // Determine if the best orientation of a footprint is -90.
1016  if( rotAllowed != 0 )
1017  {
1018  rotateFootprint( footprint, 2700.0, true );
1019  error = getOptimalFPPlacement( footprint );
1020  m_minCost *= OrientationPenalty[rotAllowed];
1021 
1022  if( bestScore > m_minCost ) // This orientation is better.
1023  {
1024  bestScore = m_minCost;
1025  bestRotation = 2700.0;
1026  }
1027  else
1028  {
1029  rotateFootprint( footprint, initialOrient, false );
1030  }
1031 
1032  if( error == AR_ABORT_PLACEMENT )
1033  goto end_of_tst;
1034  }
1035 
1036 end_of_tst:
1037 
1038  if( error == AR_ABORT_PLACEMENT )
1039  break;
1040 
1041 
1042  bestRotation += initialOrient;
1043 
1044  if( bestRotation != footprint->GetOrientation() )
1045  {
1046  rotateFootprint( footprint, bestRotation, false );
1047  }
1048 
1049  // Place footprint.
1050  placeFootprint( footprint, true, m_curPosition );
1051 
1052  footprint->CalculateBoundingBox();
1053  genModuleOnRoutingMatrix( footprint );
1054  footprint->SetIsPlaced( true );
1055  footprint->SetNeedsPlaced( false );
1057 
1058  if( m_refreshCallback )
1059  m_refreshCallback( footprint );
1060 
1061  if( m_progressReporter )
1062  {
1064 
1065  if ( !m_progressReporter->KeepRefreshing( false ) )
1066  {
1067  cancelled = true;
1068  break;
1069  }
1070  }
1071  cnt++;
1072  }
1073 
1074  m_curPosition = memopos;
1075 
1077 
1078  for( FOOTPRINT* fp : m_board->Footprints() )
1079  fp->CalculateBoundingBox();
1080 
1081  return cancelled ? AR_CANCELLED : AR_COMPLETED;
1082 }
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
PROGRESS_REPORTER * m_progressReporter
void SetNeedsPlaced(bool needsPlaced)
Definition: footprint.h:326
int getOptimalFPPlacement(FOOTPRINT *aFootprint)
int GetPlacementCost180() const
Definition: footprint.h:559
void SetIsPlaced(bool isPlaced)
Definition: footprint.h:317
int m_GridRouting
Definition: ar_matrix.h:59
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
double GetOrientation() const
Definition: footprint.h:204
virtual void Report(const wxString &aMessage)
Display aMessage in the progress bar dialog.
FOOTPRINT * pickFootprint()
Find the "best" footprint place.
void placeFootprint(FOOTPRINT *aFootprint, bool aDoNotRecreateRatsnest, const wxPoint &aPos)
bool Contains(const wxPoint &aPoint) const
Function Contains.
Definition: eda_rect.cpp:57
AR_MATRIX m_matrix
void drawPlacementRoutingMatrix()
int genPlacementRoutingMatrix()
FOOTPRINTS & Footprints()
Definition: board.h:283
#define AR_ABORT_PLACEMENT
const wxString GetReference() const
Function GetReference.
Definition: footprint.h:440
void genModuleOnRoutingMatrix(FOOTPRINT *aFootprint)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
void rotateFootprint(FOOTPRINT *aFootprint, double angle, bool incremental)
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:128
#define _(s)
Definition: 3d_actions.cpp:33
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
static const double OrientationPenalty[11]
int GetPlacementCost90() const
Definition: footprint.h:562
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)
static constexpr int Millimeter2iu(double mm)
std::function< int(FOOTPRINT *aFootprint)> m_refreshCallback
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
Definition: footprint.cpp:565

References _, PROGRESS_REPORTER::AdvanceProgress(), AR_ABORT_PLACEMENT, AR_CANCELLED, AR_COMPLETED, AR_FAILURE, FOOTPRINT::CalculateBoundingBox(), EDA_RECT::Contains(), drawPlacementRoutingMatrix(), BOARD::Footprints(), Format(), genModuleOnRoutingMatrix(), genPlacementRoutingMatrix(), getOptimalFPPlacement(), FOOTPRINT::GetOrientation(), FOOTPRINT::GetPlacementCost180(), FOOTPRINT::GetPlacementCost90(), FOOTPRINT::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, Millimeter2iu(), COMMIT::Modify(), OrientationPenalty, pickFootprint(), placeFootprint(), PROGRESS_REPORTER::Report(), rotateFootprint(), FOOTPRINT::SetIsPlaced(), PROGRESS_REPORTER::SetMaxProgress(), FOOTPRINT::SetNeedsPlaced(), PROGRESS_REPORTER::SetTitle(), and AR_MATRIX::UnInitRoutingMatrix().

Referenced by AUTOPLACE_TOOL::autoplace().

◆ buildFpAreas()

void AR_AUTOPLACER::buildFpAreas ( FOOTPRINT aFootprint,
int  aFpClearance 
)
private

Definition at line 335 of file ar_autoplacer.cpp.

336 {
339 
340  aFootprint->BuildPolyCourtyards();
341  m_fpAreaTop = aFootprint->GetPolyCourtyardFront();
342  m_fpAreaBottom = aFootprint->GetPolyCourtyardBack();
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( PAD* pad : aFootprint->Pads() )
361  {
362  int margin = (m_matrix.m_GridRouting / 2) + pad->GetOwnClearance( pad->GetLayer() );
363  addPad( pad, margin );
364  }
365 }
void BuildPolyCourtyards(OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Builds complex polygons of the courtyard areas from graphic items on the courtyard layers.
Definition: footprint.cpp:1719
SHAPE_POLY_SET & GetPolyCourtyardFront()
Used in DRC to test the courtyard area (a complex polygon)
Definition: footprint.h:672
int m_GridRouting
Definition: ar_matrix.h:59
SHAPE_POLY_SET & GetPolyCourtyardBack()
Definition: footprint.h:673
PADS & Pads()
Definition: footprint.h:182
AR_MATRIX m_matrix
const wxPoint GetEnd() const
Definition: eda_rect.h:116
SHAPE_POLY_SET m_fpAreaBottom
LSET is a set of PCB_LAYER_IDs.
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
SHAPE_POLY_SET m_fpAreaTop
void addFpBody(wxPoint aStart, wxPoint aEnd, LSET aLayerMask)
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
Definition: footprint.cpp:628
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
Definition: pad.h:59
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Definition: board_item.h:185
void addPad(PAD *aPad, int aClearance)
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363

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

Referenced by genModuleOnRoutingMatrix(), and testFootprintOnBoard().

◆ calculateKeepOutArea()

unsigned int AR_AUTOPLACER::calculateKeepOutArea ( const EDA_RECT aRect,
int  side 
)
private

Definition at line 496 of file ar_autoplacer.cpp.

497 {
498  wxPoint start = aRect.GetOrigin();
499  wxPoint end = aRect.GetEnd();
500 
501  start -= m_matrix.m_BrdBox.GetOrigin();
502  end -= m_matrix.m_BrdBox.GetOrigin();
503 
504  int row_min = start.y / m_matrix.m_GridRouting;
505  int row_max = end.y / m_matrix.m_GridRouting;
506  int col_min = start.x / m_matrix.m_GridRouting;
507  int col_max = end.x / m_matrix.m_GridRouting;
508 
509  if( start.y > row_min * m_matrix.m_GridRouting )
510  row_min++;
511 
512  if( start.x > col_min * m_matrix.m_GridRouting )
513  col_min++;
514 
515  if( row_min < 0 )
516  row_min = 0;
517 
518  if( row_max >= ( m_matrix.m_Nrows - 1 ) )
519  row_max = m_matrix.m_Nrows - 1;
520 
521  if( col_min < 0 )
522  col_min = 0;
523 
524  if( col_max >= ( m_matrix.m_Ncols - 1 ) )
525  col_max = m_matrix.m_Ncols - 1;
526 
527  unsigned int keepOutCost = 0;
528 
529  for( int row = row_min; row <= row_max; row++ )
530  {
531  for( int col = col_min; col <= col_max; col++ )
532  {
533  // m_matrix.GetDist returns the "cost" of the cell
534  // at position (row, col)
535  // in autoplace this is the cost of the cell, if it is
536  // inside aRect
537  keepOutCost += m_matrix.GetDist( row, col, side );
538  }
539  }
540 
541  return keepOutCost;
542 }
int m_Ncols
Definition: ar_matrix.h:61
int m_GridRouting
Definition: ar_matrix.h:59
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
AR_MATRIX m_matrix
const wxPoint GetEnd() const
Definition: eda_rect.h:116
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
int m_Nrows
Definition: ar_matrix.h:61
DIST_CELL GetDist(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:234

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 testFootprintOnBoard().

◆ computePlacementRatsnestCost()

double AR_AUTOPLACER::computePlacementRatsnestCost ( FOOTPRINT aFootprint,
const wxPoint &  aOffset 
)
private

Definition at line 713 of file ar_autoplacer.cpp.

714 {
715  double curr_cost;
716  VECTOR2I start; // start point of a ratsnest
717  VECTOR2I end; // end point of a ratsnest
718  int dx, dy;
719 
720  curr_cost = 0;
721 
722  for( PAD* pad : aFootprint->Pads() )
723  {
724  const PAD* nearest = nearestPad( aFootprint, pad, aOffset );
725 
726  if( !nearest )
727  continue;
728 
729  start = VECTOR2I( pad->GetPosition() ) - VECTOR2I(aOffset);
730  end = VECTOR2I( nearest->GetPosition() );
731 
732  //m_overlay->SetIsStroke( true );
733  //m_overlay->SetStrokeColor( COLOR4D(0.0, 1.0, 0.0, 1.0) );
734  //m_overlay->Line( start, end );
735 
736  // Cost of the ratsnest.
737  dx = end.x - start.x;
738  dy = end.y - start.y;
739 
740  dx = abs( dx );
741  dy = abs( dy );
742 
743  // ttry to have always dx >= dy to calculate the cost of the rastsnet
744  if( dx < dy )
745  std::swap( dx, dy );
746 
747  // Cost of the connection = length + penalty due to the slope
748  // dx is the biggest length relative to the X or Y axis
749  // the penalty is max for 45 degrees ratsnests,
750  // and 0 for horizontal or vertical ratsnests.
751  // For Horizontal and Vertical ratsnests, dy = 0;
752  double conn_cost = hypot( dx, dy * 2.0 );
753  curr_cost += conn_cost; // Total cost = sum of costs of each connection
754  }
755 
756  return curr_cost;
757 }
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
PADS & Pads()
Definition: footprint.h:182
const PAD * nearestPad(FOOTPRINT *aRefFP, PAD *aRefPad, const wxPoint &aOffset)
wxPoint GetPosition() const override
Definition: pad.h:167
Definition: pad.h:59

References PAD::GetPosition(), nearestPad(), FOOTPRINT::Pads(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by getOptimalFPPlacement().

◆ drawPlacementRoutingMatrix()

void AR_AUTOPLACER::drawPlacementRoutingMatrix ( )
private

Definition at line 846 of file ar_autoplacer.cpp.

847 {
848  // Draw the board free area
849  m_overlay->Clear();
850  m_overlay->SetIsFill( true );
851  m_overlay->SetIsStroke( false );
852 
853  SHAPE_POLY_SET freeArea = m_topFreeArea;
854  freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
855 
856  // Draw the free polygon areas, top side:
857  if( freeArea.OutlineCount() > 0 )
858  {
859  m_overlay->SetIsFill( true );
860  m_overlay->SetIsStroke( false );
861  m_overlay->SetFillColor( COLOR4D(0.7, 0.0, 0.1, 0.2) );
862  m_overlay->Polygon( freeArea );
863  }
864 
865  freeArea = m_bottomFreeArea;
866  freeArea.Fracture( SHAPE_POLY_SET::PM_FAST );
867 
868  // Draw the free polygon areas, bottom side:
869  if( freeArea.OutlineCount() > 0 )
870  {
871  m_overlay->SetFillColor( COLOR4D(0.0, 0.7, 0.0, 0.2) );
872  m_overlay->Polygon( freeArea );
873  }
874 }
SHAPE_POLY_SET m_topFreeArea
int OutlineCount() const
Returns the number of outlines in the set
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
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100

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

Referenced by AutoplaceFootprints().

◆ fillMatrix()

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 159 of file ar_autoplacer.cpp.

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

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().

◆ genModuleOnRoutingMatrix()

void AR_AUTOPLACER::genModuleOnRoutingMatrix ( FOOTPRINT aFootprint)
private

Definition at line 368 of file ar_autoplacer.cpp.

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( PAD* pad : Module->Pads() )
415  {
416  int margin = (m_matrix.m_GridRouting / 2) + pad->GetOwnClearance( pad->GetLayer() );
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
int GetX() const
Definition: eda_rect.h:111
int m_GridRouting
Definition: ar_matrix.h:59
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:615
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
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:808
#define AR_GAIN
#define AR_KEEPOUT_MARGIN
int GetBottom() const
Definition: eda_rect.h:124
void PlacePad(PAD *aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:913
AR_MATRIX m_matrix
SHAPE_POLY_SET m_fpAreaBottom
LSET is a set of PCB_LAYER_IDs.
int GetRight() const
Definition: eda_rect.h:121
SHAPE_POLY_SET m_bottomFreeArea
SHAPE_POLY_SET m_fpAreaTop
#define CELL_IS_MODULE
void buildFpAreas(FOOTPRINT *aFootprint, int aFpClearance)
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetY() const
Definition: eda_rect.h:112
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
Definition: pad.h:59
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363

References AR_GAIN, AR_KEEPOUT_MARGIN, B_Cu, SHAPE_POLY_SET::BooleanSubtract(), buildFpAreas(), CELL_IS_MODULE, AR_MATRIX::CreateKeepOutRectangle(), F_Cu, EDA_RECT::GetBottom(), FOOTPRINT::GetBoundingBox(), BOARD_ITEM::GetLayer(), FOOTPRINT::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, FOOTPRINT::Pads(), AR_MATRIX::PlacePad(), SHAPE_POLY_SET::PM_FAST, AR_MATRIX::TraceFilledRectangle(), and AR_MATRIX::WRITE_OR_CELL.

Referenced by AutoplaceFootprints().

◆ genPlacementRoutingMatrix()

int AR_AUTOPLACER::genPlacementRoutingMatrix ( )
private

Definition at line 106 of file ar_autoplacer.cpp.

107 {
109 
111 
112  if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 )
113  return 0;
114 
115  // Build the board shape
119 
120  m_matrix.ComputeMatrixSize( bbox );
121  int nbCells = m_matrix.m_Ncols * m_matrix.m_Nrows;
122 
123  // Choose the number of board sides.
128 
129  // Fill (mark) the cells inside the board:
130  fillMatrix();
131 
132  // Other obstacles can be added here:
133  for( auto drawing : m_board->Drawings() )
134  {
135  switch( drawing->Type() )
136  {
137  case PCB_SHAPE_T:
138  if( drawing->GetLayer() != Edge_Cuts )
139  {
142  }
143  break;
144 
145  default:
146  break;
147  }
148  }
149 
150  // Initialize top layer. to the same value as the bottom layer
153  nbCells * sizeof(AR_MATRIX::MATRIX_CELL) );
154 
155  return 1;
156 }
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:91
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
Definition: board.cpp:1845
#define CELL_IS_HOLE
void TraceSegmentPcb(PCB_SHAPE *pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic)
Definition: ar_matrix.cpp:765
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
int m_Ncols
Definition: ar_matrix.h:61
const EDA_RECT GetBoardEdgesBoundingBox() const
Returns the board bounding box calculated using exclusively the board edges (graphics on Edge....
Definition: board.h:777
int m_GridRouting
Definition: ar_matrix.h:59
int GetWidth() const
Definition: eda_rect.h:119
AR_MATRIX m_matrix
PCB_LAYER_ID m_routeLayerTop
Definition: ar_matrix.h:65
#define CELL_IS_EDGE
SHAPE_POLY_SET m_boardShape
int m_Nrows
Definition: ar_matrix.h:61
MATRIX_CELL * m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]
Definition: ar_matrix.h:55
SHAPE_POLY_SET m_bottomFreeArea
int GetHeight() const
Definition: eda_rect.h:120
bool fillMatrix()
fills m_matrix cells from m_boardShape.
void UnInitRoutingMatrix()
Definition: ar_matrix.cpp:128
int m_RoutingLayersCount
Definition: ar_matrix.h:58
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
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:61
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:91
DRAWINGS & Drawings()
Definition: board.h:286
PCB_LAYER_ID m_routeLayerBottom
Definition: ar_matrix.h:66

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_SHAPE_T, AR_MATRIX::TraceSegmentPcb(), AR_MATRIX::UnInitRoutingMatrix(), and AR_MATRIX::WRITE_CELL.

Referenced by AutoplaceFootprints().

◆ getOptimalFPPlacement()

int AR_AUTOPLACER::getOptimalFPPlacement ( FOOTPRINT aFootprint)
private

Definition at line 587 of file ar_autoplacer.cpp.

588 {
589  int error = 1;
590  wxPoint lastPosOK;
591  double min_cost, curr_cost, Score;
592  bool testOtherSide;
593 
594  aFootprint->CalculateBoundingBox();
595 
596  lastPosOK = m_matrix.m_BrdBox.GetOrigin();
597 
598  wxPoint fpPos = aFootprint->GetPosition();
599  EDA_RECT fpBBox = aFootprint->GetFootprintRect();
600 
601  // Move fpBBox to have the footprint position at (0,0)
602  fpBBox.Move( -fpPos );
603  wxPoint fpBBoxOrg = fpBBox.GetOrigin();
604 
605  // Calculate the limit of the footprint position, relative to the routing matrix area
606  wxPoint xylimit = m_matrix.m_BrdBox.GetEnd() - fpBBox.GetEnd();
607 
608  wxPoint initialPos = m_matrix.m_BrdBox.GetOrigin() - fpBBoxOrg;
609 
610  // Stay on grid.
611  initialPos.x -= initialPos.x % m_matrix.m_GridRouting;
612  initialPos.y -= initialPos.y % m_matrix.m_GridRouting;
613 
614  m_curPosition = initialPos;
615  wxPoint fpOffset = fpPos - m_curPosition;
616 
617  // Examine pads, and set testOtherSide to true if a footprint has at least 1 pad through.
618  testOtherSide = false;
619 
621  {
622  LSET other( aFootprint->GetLayer() == B_Cu ? F_Cu : B_Cu );
623 
624  for( PAD* pad : aFootprint->Pads() )
625  {
626  if( !( pad->GetLayerSet() & other ).any() )
627  continue;
628 
629  testOtherSide = true;
630  break;
631  }
632  }
633 
634  fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
635 
636  min_cost = -1.0;
637 // m_frame->SetStatusText( wxT( "Score ??, pos ??" ) );
638 
639 
640  for( ; m_curPosition.x < xylimit.x; m_curPosition.x += m_matrix.m_GridRouting )
641  {
642  m_curPosition.y = initialPos.y;
643 
644  for( ; m_curPosition.y < xylimit.y; m_curPosition.y += m_matrix.m_GridRouting )
645  {
646 
647  fpBBox.SetOrigin( fpBBoxOrg + m_curPosition );
648  fpOffset = fpPos - m_curPosition;
649  int keepOutCost = testFootprintOnBoard( aFootprint, testOtherSide, fpOffset );
650 
651  if( keepOutCost >= 0 ) // i.e. if the footprint can be put here
652  {
653  error = 0;
654  // m_frame->build_ratsnest_footprint( aFootprint ); // fixme
655  curr_cost = computePlacementRatsnestCost( aFootprint, fpOffset );
656  Score = curr_cost + keepOutCost;
657 
658  if( (min_cost >= Score ) || (min_cost < 0 ) )
659  {
660  lastPosOK = m_curPosition;
661  min_cost = Score;
662  wxString msg;
663 /* msg.Printf( wxT( "Score %g, pos %s, %s" ),
664  min_cost,
665  GetChars( ::CoordinateToString( LastPosOK.x ) ),
666  GetChars( ::CoordinateToString( LastPosOK.y ) ) );
667  m_frame->SetStatusText( msg );*/
668  }
669  }
670  }
671  }
672 
673  // Regeneration of the modified variable.
674  m_curPosition = lastPosOK;
675 
676  m_minCost = min_cost;
677  return error;
678 }
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
Definition: eda_rect.cpp:51
int m_GridRouting
Definition: ar_matrix.h:59
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
PADS & Pads()
Definition: footprint.h:182
AR_MATRIX m_matrix
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Build and returns the boundary box of the footprint excluding any text.
Definition: footprint.cpp:579
const wxPoint GetEnd() const
Definition: eda_rect.h:116
LSET is a set of PCB_LAYER_IDs.
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
int testFootprintOnBoard(FOOTPRINT *aFootprint, bool TstOtherSide, const wxPoint &aOffset)
int m_RoutingLayersCount
Definition: ar_matrix.h:58
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
wxPoint GetPosition() const override
Definition: footprint.h:200
wxPoint m_curPosition
Definition: pad.h:59
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Definition: board_item.h:185
void CalculateBoundingBox()
Function CalculateBoundingBox calculates the bounding box in board coordinates.
Definition: footprint.cpp:565
double computePlacementRatsnestCost(FOOTPRINT *aFootprint, const wxPoint &aOffset)

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

Referenced by AutoplaceFootprints().

◆ nearestPad()

const PAD * AR_AUTOPLACER::nearestPad ( FOOTPRINT aRefFP,
PAD aRefPad,
const wxPoint &  aOffset 
)
private

Definition at line 681 of file ar_autoplacer.cpp.

682 {
683  const PAD* nearest = nullptr;
684  int64_t nearestDist = INT64_MAX;
685 
686  for( FOOTPRINT* footprint : m_board->Footprints() )
687  {
688  if ( footprint == aRefFP )
689  continue;
690 
691  if( !m_matrix.m_BrdBox.Contains( footprint->GetPosition() ) )
692  continue;
693 
694  for( PAD* pad: footprint->Pads() )
695  {
696  if( pad->GetNetCode() != aRefPad->GetNetCode() || pad->GetNetCode() <= 0 )
697  continue;
698 
699  auto dist = (VECTOR2I( aRefPad->GetPosition() - aOffset ) - VECTOR2I( pad->GetPosition() ) ).EuclideanNorm();
700 
701  if ( dist < nearestDist )
702  {
703  nearestDist = dist;
704  nearest = pad;
705  }
706  }
707  }
708 
709  return nearest;
710 }
int GetNetCode() const
Function GetNetCode.
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
bool Contains(const wxPoint &aPoint) const
Function Contains.
Definition: eda_rect.cpp:57
AR_MATRIX m_matrix
FOOTPRINTS & Footprints()
Definition: board.h:283
wxPoint GetPosition() const override
Definition: pad.h:167
Definition: pad.h:59

References EDA_RECT::Contains(), BOARD::Footprints(), BOARD_CONNECTED_ITEM::GetNetCode(), PAD::GetPosition(), m_board, AR_MATRIX::m_BrdBox, and m_matrix.

Referenced by computePlacementRatsnestCost().

◆ pickFootprint()

FOOTPRINT * AR_AUTOPLACER::pickFootprint ( )
private

Find the "best" footprint place.

The criteria are:

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

Definition at line 782 of file ar_autoplacer.cpp.

783 {
784  std::vector<FOOTPRINT*> fpList;
785 
786 
787  for( FOOTPRINT* footprint : m_board->Footprints() )
788  {
789  footprint->CalculateBoundingBox();
790  fpList.push_back( footprint );
791  }
792 
793  sort( fpList.begin(), fpList.end(), sortFootprintsByComplexity );
794 
795  for( unsigned kk = 0; kk < fpList.size(); kk++ )
796  {
797  FOOTPRINT* footprint = fpList[kk];
798  footprint->SetFlag( 0 );
799 
800  if( !footprint->NeedsPlaced() )
801  continue;
802 
803  m_connectivity->Update( footprint );
804  }
805 
806  m_connectivity->RecalculateRatsnest();
807 
808  for( unsigned kk = 0; kk < fpList.size(); kk++ )
809  {
810  FOOTPRINT* footprint = fpList[kk];
811 
812  auto edges = m_connectivity->GetRatsnestForComponent( footprint, true );
813 
814  footprint->SetFlag( edges.size() ) ;
815  }
816 
817  sort( fpList.begin(), fpList.end(), sortFootprintsByRatsnestSize );
818 
819  // Search for "best" footprint.
820  FOOTPRINT* bestFootprint = nullptr;
821  FOOTPRINT* altFootprint = nullptr;
822 
823  for( unsigned ii = 0; ii < fpList.size(); ii++ )
824  {
825  FOOTPRINT* footprint = fpList[ii];
826 
827  if( !footprint->NeedsPlaced() )
828  continue;
829 
830  altFootprint = footprint;
831 
832  if( footprint->GetFlag() == 0 )
833  continue;
834 
835  bestFootprint = footprint;
836  break;
837  }
838 
839  if( bestFootprint )
840  return bestFootprint;
841  else
842  return altFootprint;
843 }
bool NeedsPlaced() const
Definition: footprint.h:325
int GetFlag() const
Definition: footprint.h:254
FOOTPRINTS & Footprints()
Definition: board.h:283
void SetFlag(int aFlag)
Definition: footprint.h:252
static bool sortFootprintsByRatsnestSize(FOOTPRINT *ref, FOOTPRINT *compare)
static bool sortFootprintsByComplexity(FOOTPRINT *ref, FOOTPRINT *compare)
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity

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

Referenced by AutoplaceFootprints().

◆ placeFootprint()

void AR_AUTOPLACER::placeFootprint ( FOOTPRINT aFootprint,
bool  aDoNotRecreateRatsnest,
const wxPoint &  aPos 
)
private

Definition at line 95 of file ar_autoplacer.cpp.

97 {
98  if( !aFootprint )
99  return;
100 
101  aFootprint->SetPosition( aPos );
102  m_connectivity->Update( aFootprint );
103 }
void SetPosition(const wxPoint &aPos) override
Definition: footprint.cpp:1346
std::unique_ptr< CONNECTIVITY_DATA > m_connectivity

References m_connectivity, and FOOTPRINT::SetPosition().

Referenced by AutoplaceFootprints().

◆ rotateFootprint()

void AR_AUTOPLACER::rotateFootprint ( FOOTPRINT aFootprint,
double  angle,
bool  incremental 
)
private

Definition at line 274 of file ar_autoplacer.cpp.

275 {
276  if( aFootprint == NULL )
277  return;
278 
279  if( incremental )
280  aFootprint->SetOrientation( aFootprint->GetOrientation() + angle );
281  else
282  aFootprint->SetOrientation( angle );
283 
284 
285  m_board->GetConnectivity()->Update( aFootprint );
286 }
double GetOrientation() const
Definition: footprint.h:204
#define NULL
void SetOrientation(double aNewAngle)
Definition: footprint.cpp:1446
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
Definition: board.h:382
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

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

Referenced by AutoplaceFootprints().

◆ SetOverlay()

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 68 of file ar_autoplacer.h.

69  {
70  m_overlay = aOverlay;
71  }
std::shared_ptr< KIGFX::VIEW_OVERLAY > m_overlay

References m_overlay.

Referenced by AUTOPLACE_TOOL::autoplace().

◆ SetProgressReporter()

void AR_AUTOPLACER::SetProgressReporter ( PROGRESS_REPORTER aReporter)
inline

Definition at line 82 of file ar_autoplacer.h.

83  {
84  m_progressReporter = aReporter;
85  }
PROGRESS_REPORTER * m_progressReporter

References m_progressReporter.

Referenced by AUTOPLACE_TOOL::autoplace().

◆ SetRefreshCallback()

void AR_AUTOPLACER::SetRefreshCallback ( std::function< int(FOOTPRINT *aFootprint)>  aCallback)
inline

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

Definition at line 77 of file ar_autoplacer.h.

78  {
79  m_refreshCallback = aCallback;
80  }
std::function< int(FOOTPRINT *aFootprint)> m_refreshCallback

References m_refreshCallback.

Referenced by AUTOPLACE_TOOL::autoplace().

◆ testFootprintOnBoard()

int AR_AUTOPLACER::testFootprintOnBoard ( FOOTPRINT aFootprint,
bool  TstOtherSide,
const wxPoint &  aOffset 
)
private

Definition at line 549 of file ar_autoplacer.cpp.

551 {
552  int side = AR_SIDE_TOP;
553  int otherside = AR_SIDE_BOTTOM;
554 
555  if( aFootprint->GetLayer() == B_Cu )
556  {
557  side = AR_SIDE_BOTTOM; otherside = AR_SIDE_TOP;
558  }
559 
560  EDA_RECT fpBBox = aFootprint->GetFootprintRect();
561  fpBBox.Move( -aOffset );
562 
563  buildFpAreas( aFootprint, 0 );
564 
565  int diag = //testModuleByPolygon( aFootprint, side, aOffset );
566  testRectangle( fpBBox, side );
567 
568  if( diag != AR_FREE_CELL )
569  return diag;
570 
571  if( TstOtherSide )
572  {
573  diag = //testModuleByPolygon( aFootprint, otherside, aOffset );
574  testRectangle( fpBBox, otherside );
575 
576  if( diag != AR_FREE_CELL )
577  return diag;
578  }
579 
580  int marge = ( m_matrix.m_GridRouting * aFootprint->GetPadCount() ) / AR_GAIN;
581 
582  fpBBox.Inflate( marge );
583  return calculateKeepOutArea( fpBBox, side );
584 }
#define AR_SIDE_BOTTOM
Definition: ar_matrix.h:43
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
Definition: eda_rect.cpp:51
#define AR_SIDE_TOP
Definition: ar_matrix.h:42
unsigned GetPadCount(INCLUDE_NPTH_T aIncludeNPTH=INCLUDE_NPTH_T(INCLUDE_NPTH)) const
GetPadCount returns the number of pads.
Definition: footprint.cpp:916
int m_GridRouting
Definition: ar_matrix.h:59
#define AR_GAIN
AR_MATRIX m_matrix
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Build and returns the boundary box of the footprint excluding any text.
Definition: footprint.cpp:579
unsigned int calculateKeepOutArea(const EDA_RECT &aRect, int side)
int testRectangle(const EDA_RECT &aRect, int side)
void buildFpAreas(FOOTPRINT *aFootprint, int aFpClearance)
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Definition: board_item.h:185
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363

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

Referenced by getOptimalFPPlacement().

◆ testRectangle()

int AR_AUTOPLACER::testRectangle ( const EDA_RECT aRect,
int  side 
)
private

Definition at line 439 of file ar_autoplacer.cpp.

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 }
int m_Ncols
Definition: ar_matrix.h:61
int m_GridRouting
Definition: ar_matrix.h:59
EDA_RECT m_BrdBox
Definition: ar_matrix.h:60
AR_MATRIX m_matrix
const wxPoint GetEnd() const
Definition: eda_rect.h:116
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
MATRIX_CELL GetCell(int aRow, int aCol, int aSide)
Definition: ar_matrix.cpp:169
int m_Nrows
Definition: ar_matrix.h:61
#define CELL_IS_ZONE
#define CELL_IS_MODULE
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.
Definition: eda_rect.cpp:363

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 testFootprintOnBoard().

Member Data Documentation

◆ m_board

BOARD* AR_AUTOPLACER::m_board
private

◆ m_boardShape

SHAPE_POLY_SET AR_AUTOPLACER::m_boardShape
private

Definition at line 128 of file ar_autoplacer.h.

Referenced by fillMatrix(), and genPlacementRoutingMatrix().

◆ m_bottomFreeArea

SHAPE_POLY_SET AR_AUTOPLACER::m_bottomFreeArea
private

◆ m_connectivity

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

Definition at line 139 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), pickFootprint(), and placeFootprint().

◆ m_curPosition

wxPoint AR_AUTOPLACER::m_curPosition
private

Definition at line 134 of file ar_autoplacer.h.

Referenced by AutoplaceFootprints(), and getOptimalFPPlacement().

◆ m_fpAreaBottom

SHAPE_POLY_SET AR_AUTOPLACER::m_fpAreaBottom
private

Definition at line 130 of file ar_autoplacer.h.

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

◆ m_fpAreaTop

SHAPE_POLY_SET AR_AUTOPLACER::m_fpAreaTop
private

Definition at line 129 of file ar_autoplacer.h.

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

◆ m_gridSize

int AR_AUTOPLACER::m_gridSize
private

Definition at line 136 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), and AutoplaceFootprints().

◆ m_matrix

◆ m_minCost

double AR_AUTOPLACER::m_minCost
private

Definition at line 135 of file ar_autoplacer.h.

Referenced by AR_AUTOPLACER(), AutoplaceFootprints(), and getOptimalFPPlacement().

◆ m_overlay

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

Definition at line 138 of file ar_autoplacer.h.

Referenced by drawPlacementRoutingMatrix(), and SetOverlay().

◆ m_progressReporter

PROGRESS_REPORTER* AR_AUTOPLACER::m_progressReporter
private

Definition at line 141 of file ar_autoplacer.h.

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

◆ m_refreshCallback

std::function<int( FOOTPRINT* aFootprint )> AR_AUTOPLACER::m_refreshCallback
private

Definition at line 140 of file ar_autoplacer.h.

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

◆ m_topFreeArea

SHAPE_POLY_SET AR_AUTOPLACER::m_topFreeArea
private

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