Pcbnew: spread and pick up new footprints when loaded.

This commit is contained in:
Jon Neal 2016-01-10 16:24:13 -05:00 committed by Chris Pavlina
parent 7e2af163dd
commit f309eaab00
6 changed files with 85 additions and 54 deletions

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2010 Jean-Pierre Charras, jp.charras@wanadoo.fr
* Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -1587,12 +1587,17 @@ public:
* Function SpreadFootprints
* Footprints (after loaded by reading a netlist for instance) are moved
* to be in a small free area (outside the current board) without overlapping.
* @param aFootprintsOutsideBoardOnly: true to move only
* footprints outside the board outlines
* (they are outside if the position of a footprint is outside
* the board outlines bounding box
* @param aFootprints: a list of footprints to be spread out.
* @param aMoveFootprintsOutsideBoardOnly: true to move only
* footprints outside the board outlines
* (they are outside if the position of a footprint is outside
* the board outlines bounding box).
* @param aCheckForBoardEdges: true to try to place footprints outside of
* board edges.
*/
void SpreadFootprints( bool aFootprintsOutsideBoardOnly );
void SpreadFootprints( std::vector<MODULE*>* aFootprints,
bool aMoveFootprintsOutsideBoardOnly,
bool aCheckForBoardEdges );
/**
* Function AutoPlaceModule

View File

@ -5,7 +5,7 @@
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
*
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -139,8 +139,15 @@ void PCB_EDIT_FRAME::OnPlaceOrRouteFootprints( wxCommandEvent& event )
DisplayError( this, _( "No footprint found!" ) );
return;
}
else
{
MODULE* footprint = GetBoard()->m_Modules;
std::vector<MODULE*> footprintList;
for( ; footprint != NULL; footprint = footprint->Next() )
footprintList.push_back( footprint );
SpreadFootprints( id == ID_POPUP_PCB_SPREAD_NEW_MODULES );
SpreadFootprints( &footprintList, id == ID_POPUP_PCB_SPREAD_NEW_MODULES, true );
}
break;
case ID_POPUP_PCB_AUTOROUTE_ALL_MODULES:

View File

@ -5,7 +5,7 @@
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
*
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -35,6 +35,7 @@
*/
#include <algorithm>
#include <boost/foreach.hpp>
#include <fctsys.h>
#include <convert_to_biu.h>
@ -95,8 +96,8 @@ void fillRectList( CSubRectArray& vecSubRects, std::vector <EDA_RECT>& aRectList
// Spread a list of rectangles inside a placement area
void spreadRectangles( CRectPlacement& aPlacementArea,
CSubRectArray& vecSubRects,
int areaSizeX, int areaSizeY )
CSubRectArray& vecSubRects,
int areaSizeX, int areaSizeY )
{
areaSizeX/= scale;
areaSizeY/= scale;
@ -135,8 +136,9 @@ void spreadRectangles( CRectPlacement& aPlacementArea,
void moveFootprintsInArea( CRectPlacement& aPlacementArea,
std::vector <MODULE*>& aModuleList, EDA_RECT& aFreeArea,
bool aFindAreaOnly )
std::vector <MODULE*>& aModuleList,
EDA_RECT& aFreeArea,
bool aFindAreaOnly )
{
CSubRectArray vecSubRects;
@ -163,83 +165,82 @@ void moveFootprintsInArea( CRectPlacement& aPlacementArea,
}
}
static bool sortModulesbySheetPath( MODULE* ref, MODULE* compare );
static bool sortFootprintsbySheetPath( MODULE* ref, MODULE* compare );
/* Function to move components in a rectangular area format 4 / 3,
* starting from the mouse cursor
* The components with the FIXED status set are not moved
*/
void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly )
void PCB_EDIT_FRAME::SpreadFootprints( std::vector<MODULE*>* aFootprints,
bool aMoveFootprintsOutsideBoardOnly,
bool aCheckForBoardEdges )
{
EDA_RECT bbox = GetBoard()->ComputeBoundingBox( true );
bool edgesExist = ( bbox.GetWidth() || bbox.GetHeight() );
// if aFootprintsOutsideBoardOnly is true, and if board outline exists,
// wue have to filter footprints to move:
bool outsideBrdFilter = aMoveFootprintsOutsideBoardOnly && edgesExist;
// no edges exist
if( aFootprintsOutsideBoardOnly && !edgesExist )
if( aMoveFootprintsOutsideBoardOnly && !edgesExist )
{
DisplayError( this,
_( "Could not automatically place footprints. No board outlines detected." ) );
return;
}
// if aFootprintsOutsideBoardOnly is true, and if board outline exists,
// wue have to filter footprints to move:
bool outsideBrdFilter = aFootprintsOutsideBoardOnly && edgesExist;
// Build candidate list
// calculate also the area needed by these footprints
MODULE* module = GetBoard()->m_Modules;
std::vector <MODULE*> moduleList;
std::vector <MODULE*> footprintList;
for( ; module != NULL; module = module->Next() )
BOOST_FOREACH( MODULE* footprint, *aFootprints )
{
module->CalculateBoundingBox();
footprint->CalculateBoundingBox();
if( outsideBrdFilter )
{
if( bbox.Contains( module->GetPosition() ) )
if( bbox.Contains( footprint->GetPosition() ) )
continue;
}
if( module->IsLocked() )
if( footprint->IsLocked() )
continue;
moduleList.push_back(module);
footprintList.push_back( footprint );
}
if( moduleList.size() == 0 ) // Nothing to do
if( footprintList.empty() )
return;
// sort footprints by sheet path. we group them later by sheet
sort( moduleList.begin(), moduleList.end(), sortModulesbySheetPath );
sort( footprintList.begin(), footprintList.end(), sortFootprintsbySheetPath );
// Undo command: init undo list
PICKED_ITEMS_LIST undoList;
undoList.m_Status = UR_CHANGED;
ITEM_PICKER picker( NULL, UR_CHANGED );
for( unsigned ii = 0; ii < moduleList.size(); ii++ )
BOOST_FOREACH( MODULE* footprint, footprintList )
{
module = moduleList[ii];
// Undo: add copy of module to undo list
picker.SetItem( module );
picker.SetLink( module->Clone() );
// Undo: add copy of the footprint to undo list
picker.SetItem( footprint );
picker.SetLink( footprint->Clone() );
undoList.PushItem( picker );
}
// Extract and place footprints by sheet
std::vector <MODULE*> moduleListBySheet;
std::vector <MODULE*> footprintListBySheet;
std::vector <EDA_RECT> placementSheetAreas;
double subsurface;
double placementsurface = 0.0;
wxPoint placementAreaPosition = GetCrossHairPosition();
// We do not want to move footprints inside an existing board.
// We sometimes do not want to move footprints inside an existing board.
// move the placement area position outside the board bounding box
// to the left of the board
if( edgesExist )
if( edgesExist && aCheckForBoardEdges )
{
if( placementAreaPosition.x < bbox.GetEnd().x &&
placementAreaPosition.y < bbox.GetEnd().y )
@ -253,24 +254,25 @@ void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly )
// the first pass creates the rectangular areas to place footprints
// each sheet in schematic creates one rectangular area.
// the second pass moves footprints inside these areas
MODULE* footprint;
for( int pass = 0; pass < 2; pass++ )
{
int subareaIdx = 0;
moduleListBySheet.clear();
footprintListBySheet.clear();
subsurface = 0.0;
for( unsigned ii = 0; ii < moduleList.size(); ii++ )
for( unsigned ii = 0; ii < footprintList.size(); ii++ )
{
module = moduleList[ii];
footprint = footprintList[ii];
bool islastItem = false;
if( ii == moduleList.size() - 1 ||
( moduleList[ii]->GetPath().BeforeLast( '/' ) !=
moduleList[ii+1]->GetPath().BeforeLast( '/' ) ) )
if( ii == footprintList.size() - 1 ||
( footprintList[ii]->GetPath().BeforeLast( '/' ) !=
footprintList[ii+1]->GetPath().BeforeLast( '/' ) ) )
islastItem = true;
moduleListBySheet.push_back( module );
subsurface += module->GetArea();
footprintListBySheet.push_back( footprint );
subsurface += footprint->GetArea();
if( islastItem )
{
@ -292,7 +294,7 @@ void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly )
}
bool findAreaOnly = pass == 0;
moveFootprintsInArea( placementArea, moduleListBySheet,
moveFootprintsInArea( placementArea, footprintListBySheet,
freeArea, findAreaOnly );
if( pass == 0 )
@ -312,7 +314,7 @@ void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly )
// Prepare buffers for next sheet
subsurface = 0.0;
moduleListBySheet.clear();
footprintListBySheet.clear();
subareaIdx++;
}
}
@ -353,7 +355,7 @@ void PCB_EDIT_FRAME::SpreadFootprints( bool aFootprintsOutsideBoardOnly )
// Footprints are sorted by their sheet path.
// (the full sheet path restricted to the time stamp of the sheet itself,
// without the time stamp of the footprint ).
static bool sortModulesbySheetPath( MODULE* ref, MODULE* compare )
static bool sortFootprintsbySheetPath( MODULE* ref, MODULE* compare )
{
if( ref->GetPath().Length() == compare->GetPath().Length() )
return ref->GetPath().BeforeLast( '/' ).Cmp( compare->GetPath().BeforeLast( '/' ) ) < 0;

View File

@ -10,7 +10,7 @@
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
*
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -2259,13 +2259,14 @@ bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE_CONTAI
void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
REPORTER* aReporter )
std::vector<MODULE*>* aNewFootprints, REPORTER* aReporter )
{
unsigned i;
wxPoint bestPosition;
wxString msg;
D_PAD* pad;
MODULE* footprint;
std::vector<MODULE*> newFootprints;
if( !IsEmpty() )
{
@ -2340,6 +2341,7 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
footprint->SetParent( this );
footprint->SetPosition( bestPosition );
footprint->SetTimeStamp( GetNewTimeStamp() );
newFootprints.push_back( footprint );
Add( footprint, ADD_APPEND );
}
}
@ -2666,6 +2668,8 @@ void BOARD::ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
}
}
}
std::swap( newFootprints, *aNewFootprints );
}

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -962,7 +962,7 @@ public:
* the #BOARD. If NULL, no change reporting occurs.
*/
void ReplaceNetlist( NETLIST& aNetlist, bool aDeleteSinglePadNets,
REPORTER* aReporter = NULL );
std::vector<MODULE*>* aNewFootprints, REPORTER* aReporter = NULL );
/**
* Function SortedNetnamesList

View File

@ -7,7 +7,7 @@
* Copyright (C) 1992-2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
* Copyright (C) 1992-2013 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 1992-2016 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -66,6 +66,7 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName,
NETLIST netlist;
KIGFX::VIEW* view = GetGalCanvas()->GetView();
BOARD* board = GetBoard();
std::vector<MODULE*> newFootprints;
netlist.SetIsDryRun( aIsDryRun );
netlist.SetFindByTimeStamp( aSelectByTimeStamp );
@ -113,12 +114,24 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName,
m_toolManager->RunAction( COMMON_ACTIONS::selectionClear, true );
netlist.SortByReference();
board->ReplaceNetlist( netlist, aDeleteSinglePadNets, aReporter );
board->ReplaceNetlist( netlist, aDeleteSinglePadNets, &newFootprints, aReporter );
// If it was a dry run, nothing has changed so we're done.
if( netlist.IsDryRun() )
return;
if( IsGalCanvasActive() )
{
SpreadFootprints( &newFootprints, false, false );
BOOST_FOREACH( MODULE* footprint, newFootprints )
{
m_toolManager->RunAction( COMMON_ACTIONS::selectItem, true, footprint );
}
m_toolManager->InvokeTool( "pcbnew.InteractiveEdit" );
}
OnModify();
SetCurItem( NULL );