KiCad PCB EDA Suite
pcbnew/netlist_reader/netlist.cpp File Reference
#include <functional>
#include <fctsys.h>
#include <kiway.h>
#include <pcb_edit_frame.h>
#include "pcb_netlist.h"
#include "netlist_reader.h"
#include <reporter.h>
#include <lib_id.h>
#include <fp_lib_table.h>
#include <class_board.h>
#include <class_module.h>
#include <ratsnest/ratsnest_data.h>
#include <io_mgr.h>
#include "board_netlist_updater.h"
#include <tool/tool_manager.h>
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
#include <project/project_file.h>
#include <view/view.h>

Go to the source code of this file.

Macros

#define ALLOW_PARTIAL_FPID   1
 

Functions

void SpreadFootprints (std::vector< MODULE * > *aFootprints, wxPoint aSpreadAreaPosition)
 Footprints (after loaded by reading a netlist for instance) are moved to be in a small free area (outside the current board) without overlapping. More...
 

Macro Definition Documentation

◆ ALLOW_PARTIAL_FPID

#define ALLOW_PARTIAL_FPID   1

Definition at line 138 of file pcbnew/netlist_reader/netlist.cpp.

Function Documentation

◆ SpreadFootprints()

void SpreadFootprints ( std::vector< MODULE * > *  aFootprints,
wxPoint  aSpreadAreaPosition 
)

Footprints (after loaded by reading a netlist for instance) are moved to be in a small free area (outside the current board) without overlapping.

Parameters
aBoardis the board to edit.
aFootprintsa list of footprints to be spread out.
aSpreadAreaPositionthe position of the upper left corner of the area allowed to spread footprints

Definition at line 193 of file spread_footprints.cpp.

195 {
196  // Build candidate list
197  // calculate also the area needed by these footprints
198  std::vector <MODULE*> footprintList;
199 
200  for( MODULE* footprint : *aFootprints )
201  {
202  if( footprint->IsLocked() )
203  continue;
204 
205  footprint->CalculateBoundingBox();
206  footprintList.push_back( footprint );
207  }
208 
209  if( footprintList.empty() )
210  return;
211 
212  // sort footprints by sheet path. we group them later by sheet
213  sort( footprintList.begin(), footprintList.end(), sortFootprintsbySheetPath );
214 
215  // Extract and place footprints by sheet
216  std::vector <MODULE*> footprintListBySheet;
217  std::vector <EDA_RECT> placementSheetAreas;
218  double subsurface;
219  double placementsurface = 0.0;
220 
221  // The placement uses 2 passes:
222  // the first pass creates the rectangular areas to place footprints
223  // each sheet in schematic creates one rectangular area.
224  // the second pass moves footprints inside these areas
225  for( int pass = 0; pass < 2; pass++ )
226  {
227  int subareaIdx = 0;
228  footprintListBySheet.clear();
229  subsurface = 0.0;
230 
231  int fp_max_width = 0;
232  int fp_max_height = 0;
233 
234  for( unsigned ii = 0; ii < footprintList.size(); ii++ )
235  {
236  MODULE* footprint = footprintList[ii];
237  bool islastItem = false;
238 
239  if( ii == footprintList.size() - 1 ||
240  ( footprintList[ii]->GetPath().AsString().BeforeLast( '/' ) !=
241  footprintList[ii+1]->GetPath().AsString().BeforeLast( '/' ) ) )
242  islastItem = true;
243 
244  footprintListBySheet.push_back( footprint );
245  subsurface += footprint->GetArea( PADDING );
246 
247  // Calculate min size of placement area:
248  EDA_RECT bbox = footprint->GetFootprintRect();
249  fp_max_width = std::max( fp_max_width, bbox.GetWidth() );
250  fp_max_height = std::max( fp_max_height, bbox.GetHeight() );
251 
252  if( islastItem )
253  {
254  // end of the footprint sublist relative to the same sheet path
255  // calculate placement of the current sublist
256  EDA_RECT freeArea;
257  int Xsize_allowed = (int) ( sqrt( subsurface ) * 4.0 / 3.0 );
258  Xsize_allowed = std::max( fp_max_width, Xsize_allowed );
259 
260  int Ysize_allowed = (int) ( subsurface / Xsize_allowed );
261  Ysize_allowed = std::max( fp_max_height, Ysize_allowed );
262 
263  freeArea.SetWidth( Xsize_allowed );
264  freeArea.SetHeight( Ysize_allowed );
265  CRectPlacement placementArea;
266 
267  if( pass == 1 )
268  {
269  wxPoint areapos = placementSheetAreas[subareaIdx].GetOrigin()
270  + aSpreadAreaPosition;
271  freeArea.SetOrigin( areapos );
272  }
273 
274  bool findAreaOnly = pass == 0;
275  moveFootprintsInArea( placementArea, footprintListBySheet,
276  freeArea, findAreaOnly );
277 
278  if( pass == 0 )
279  {
280  // Populate sheet placement areas list
281  EDA_RECT sub_area;
282  sub_area.SetWidth( placementArea.GetW()*scale );
283  sub_area.SetHeight( placementArea.GetH()*scale );
284  // Add a margin around the sheet placement area:
285  sub_area.Inflate( Millimeter2iu( 1.5 ) );
286 
287  placementSheetAreas.push_back( sub_area );
288 
289  placementsurface += (double) sub_area.GetWidth()*
290  sub_area.GetHeight();
291  }
292 
293  // Prepare buffers for next sheet
294  subsurface = 0.0;
295  footprintListBySheet.clear();
296  subareaIdx++;
297  }
298  }
299 
300  // End of pass:
301  // At the end of the first pass, we have to find position of each sheet
302  // placement area
303  if( pass == 0 )
304  {
305  int Xsize_allowed = (int) ( sqrt( placementsurface ) * 4.0 / 3.0 );
306 
307  if( Xsize_allowed < 0 || Xsize_allowed > INT_MAX/2 )
308  Xsize_allowed = INT_MAX/2;
309 
310  int Ysize_allowed = (int) ( placementsurface / Xsize_allowed );
311 
312  if( Ysize_allowed < 0 || Ysize_allowed > INT_MAX/2 )
313  Ysize_allowed = INT_MAX/2;
314 
315  CRectPlacement placementArea;
316  CSubRectArray vecSubRects;
317  fillRectList( vecSubRects, placementSheetAreas );
318  spreadRectangles( placementArea, vecSubRects, Xsize_allowed, Ysize_allowed );
319 
320  for( unsigned it = 0; it < vecSubRects.size(); ++it )
321  {
322  TSubRect& srect = vecSubRects[it];
323  wxPoint pos( srect.x*scale, srect.y*scale );
324  wxSize size( srect.w*scale, srect.h*scale );
325 
326  // Avoid too large coordinates: Overlapping components
327  // are better than out of screen components
328  if( (uint64_t)pos.x + (uint64_t)size.x > INT_MAX/2 )
329  pos.x = 0;
330 
331  if( (uint64_t)pos.y + (uint64_t)size.y > INT_MAX/2 )
332  pos.y = 0;
333 
334  placementSheetAreas[srect.n].SetOrigin( pos );
335  placementSheetAreas[srect.n].SetSize( size );
336  }
337  }
338  } // End pass
339 }
double GetArea(int aPadding=0) const
int GetWidth() const
Definition: eda_rect.h:119
void SetOrigin(const wxPoint &pos)
Definition: eda_rect.h:131
EDA_RECT GetFootprintRect() const
Function GetFootprintRect() Returns the area of the module footprint excluding any text.
void fillRectList(CSubRectArray &vecSubRects, std::vector< MODULE * > &aModuleList)
const int PADDING
void SetHeight(int val)
Definition: eda_rect.h:186
int GetW() const
static bool sortFootprintsbySheetPath(MODULE *ref, MODULE *compare)
std::vector< TSubRect > CSubRectArray
void SetWidth(int val)
Definition: eda_rect.h:180
int GetHeight() const
Definition: eda_rect.h:120
const int scale
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
void moveFootprintsInArea(CRectPlacement &aPlacementArea, std::vector< MODULE * > &aModuleList, EDA_RECT &aFreeArea, bool aFindAreaOnly)
void spreadRectangles(CRectPlacement &aPlacementArea, CSubRectArray &vecSubRects, int areaSizeX, int areaSizeY)
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
int GetH() const

References fillRectList(), MODULE::GetArea(), MODULE::GetFootprintRect(), CRectPlacement::GetH(), EDA_RECT::GetHeight(), CRectPlacement::GetW(), EDA_RECT::GetWidth(), CRectPlacement::TRect::h, EDA_RECT::Inflate(), moveFootprintsInArea(), TSubRect::n, PADDING, scale, EDA_RECT::SetHeight(), EDA_RECT::SetOrigin(), EDA_RECT::SetWidth(), sortFootprintsbySheetPath(), spreadRectangles(), CRectPlacement::TRect::w, CRectPlacement::TPos::x, wxPoint::x, CRectPlacement::TPos::y, and wxPoint::y.

Referenced by PCB_EDIT_FRAME::OnNetlistChanged().