pcbnew: bring back the autoplacer tool to GAL

This commit is contained in:
Tomasz Wlostowski 2018-08-24 12:54:45 +02:00
parent 2186db976b
commit 61fb3f6d0f
18 changed files with 2554 additions and 1545 deletions

View File

@ -205,6 +205,9 @@ set( PCBNEW_CLASS_SRCS
autorouter/rect_placement/rect_placement.cpp autorouter/rect_placement/rect_placement.cpp
autorouter/spread_footprints.cpp autorouter/spread_footprints.cpp
autorouter/ar_autoplacer.cpp
autorouter/ar_matrix.cpp
autorouter/autoplacer_tool.cpp
action_plugin.cpp action_plugin.cpp
append_board_to_current.cpp append_board_to_current.cpp

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
* 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 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __AR_AUTOPLACER_H
#define __AR_AUTOPLACER_H
#include "ar_cell.h"
#include "ar_matrix.h"
#include <class_board.h>
#include <class_module.h>
#include <connectivity_data.h>
#include <view/view_overlay.h>
enum AR_CELL_STATE
{
AR_OUT_OF_BOARD = -2,
AR_OCCUIPED_BY_MODULE = -1,
AR_FREE_CELL = 0
};
enum AR_RESULT
{
AR_COMPLETED = 1,
AR_CANCELLED,
AR_FAILURE
};
class PROGRESS_REPORTER;
class AR_AUTOPLACER
{
public:
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 )
{
m_gridSize = aGrid;
}
void SetOverlay( std::shared_ptr<KIGFX::VIEW_OVERLAY> aOverlay )
{
m_overlay = aOverlay;
}
void SetRefreshCallback( std::function<int()> aCallback )
{
m_refreshCallback = aCallback;
}
void SetProgressReporter( PROGRESS_REPORTER* aReporter )
{
m_progressReporter = aReporter;
}
private:
void drawPlacementRoutingMatrix();
void rotateModule( MODULE* module, double angle, bool incremental );
int genPlacementRoutingMatrix();
void genModuleOnRoutingMatrix( MODULE* Module );
int propagate();
int testRectangle( const EDA_RECT& aRect, int side );
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 );
MODULE* pickModule();
void placeModule( MODULE* aModule, bool aDoNotRecreateRatsnest, const wxPoint& aPos );
const D_PAD* nearestPad( MODULE* aRefModule, D_PAD* aRefPad, const wxPoint& aOffset );
AR_MATRIX m_matrix;
BOARD* m_board;
wxPoint m_curPosition;
wxPoint m_moduleOffset;
double m_minCost;
int m_gridSize;
std::shared_ptr<KIGFX::VIEW_OVERLAY> m_overlay;
std::unique_ptr<CONNECTIVITY_DATA> m_connectivity;
std::function<int()> m_refreshCallback;
PROGRESS_REPORTER* m_progressReporter;
};
#endif

View File

@ -1,7 +1,3 @@
/**
* @file cell.h
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
@ -32,85 +28,84 @@
*/ */
#ifndef _CELL_H_ #ifndef _AR_CELL_H_
#define _CELL_H_ #define _AR_CELL_H_
/* Bits characterizing cell */ /* Bits characterizing cell */
#define HOLE 0x01 /* a conducting hole or obstacle */ #define CELL_IS_EMPTY 0x00
#define CELL_is_MODULE 0x02 /* auto placement occupied by a module */ #define CELL_IS_HOLE 0x01 /* a conducting hole or obstacle */
#define CELL_is_EDGE 0x20 /* Area and auto-placement: limiting cell contour (Board, Zone) */ #define CELL_IS_MODULE 0x02 /* auto placement occupied by a module */
#define CELL_is_FRIEND 0x40 /* Area and auto-placement: cell part of the net */ #define CELL_IS_EDGE 0x20 /* Area and auto-placement: limiting cell contour (Board, Zone) */
#define CELL_is_ZONE 0x80 /* Area and auto-placement: cell available */ #define CELL_IS_FRIEND 0x40 /* Area and auto-placement: cell part of the net */
#define CELL_IS_ZONE 0x80 /* Area and auto-placement: cell available */
/* Bit masks for presence of obstacles to autorouting */ /* Bit masks for presence of obstacles to autorouting */
#define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */ #define OCCUPE 1 /* Autorouting: obstacle tracks and vias. */
#define VIA_IMPOSSIBLE 2 /* Autorouting: obstacle for vias. */ #define VIA_IMPOSSIBLE 2 /* Autorouting: obstacle for vias. */
#define CURRENT_PAD 4 #define CURRENT_PAD 4
/* traces radiating outward from a hole to a side or corner */ /* traces radiating outward from a hole to a side or corner */
#define HOLE_NORTH 0x00000002L /* upward */ #define HOLE_NORTH 0x00000002L /* upward */
#define HOLE_NORTHEAST 0x00000004L /* upward and right */ #define HOLE_NORTHEAST 0x00000004L /* upward and right */
#define HOLE_EAST 0x00000008L /* to the right */ #define HOLE_EAST 0x00000008L /* to the right */
#define HOLE_SOUTHEAST 0x00000010L /* downward and right */ #define HOLE_SOUTHEAST 0x00000010L /* downward and right */
#define HOLE_SOUTH 0x00000020L /* downward */ #define HOLE_SOUTH 0x00000020L /* downward */
#define HOLE_SOUTHWEST 0x00000040L /* downward and left */ #define HOLE_SOUTHWEST 0x00000040L /* downward and left */
#define HOLE_WEST 0x00000080L /* to the left */ #define HOLE_WEST 0x00000080L /* to the left */
#define HOLE_NORTHWEST 0x00000100L /* upward and left */ #define HOLE_NORTHWEST 0x00000100L /* upward and left */
/* straight lines through the center */ /* straight lines through the center */
#define LINE_HORIZONTAL 0x00000002L /* left-to-right line */ #define LINE_HORIZONTAL 0x00000002L /* left-to-right line */
#define LINE_VERTICAL 0x00000004L /* top-to-bottom line */ #define LINE_VERTICAL 0x00000004L /* top-to-bottom line */
/* lines cutting across a corner, connecting adjacent sides */ /* lines cutting across a corner, connecting adjacent sides */
#define CORNER_NORTHEAST 0x00000008L /* upper right corner */ #define CORNER_NORTHEAST 0x00000008L /* upper right corner */
#define CORNER_SOUTHEAST 0x00000010L /* lower right corner */ #define CORNER_SOUTHEAST 0x00000010L /* lower right corner */
#define CORNER_SOUTHWEST 0x00000020L /* lower left corner */ #define CORNER_SOUTHWEST 0x00000020L /* lower left corner */
#define CORNER_NORTHWEST 0x00000040L /* upper left corner */ #define CORNER_NORTHWEST 0x00000040L /* upper left corner */
/* diagonal lines through the center */ /* diagonal lines through the center */
#define DIAG_NEtoSW 0x00000080L /* northeast to southwest */ #define DIAG_NEtoSW 0x00000080L /* northeast to southwest */
#define DIAG_SEtoNW 0x00000100L /* southeast to northwest */ #define DIAG_SEtoNW 0x00000100L /* southeast to northwest */
/* 135 degree angle side-to-far-corner lines */ /* 135 degree angle side-to-far-corner lines */
#define BENT_NtoSE 0x00000200L /* north to southeast */ #define BENT_NtoSE 0x00000200L /* north to southeast */
#define BENT_NtoSW 0x00000400L /* north to southwest */ #define BENT_NtoSW 0x00000400L /* north to southwest */
#define BENT_EtoSW 0x00000800L /* east to southwest */ #define BENT_EtoSW 0x00000800L /* east to southwest */
#define BENT_EtoNW 0x00001000L /* east to northwest */ #define BENT_EtoNW 0x00001000L /* east to northwest */
#define BENT_StoNW 0x00002000L /* south to northwest */ #define BENT_StoNW 0x00002000L /* south to northwest */
#define BENT_StoNE 0x00004000L /* south to northeast */ #define BENT_StoNE 0x00004000L /* south to northeast */
#define BENT_WtoNE 0x00008000L /* west to northeast */ #define BENT_WtoNE 0x00008000L /* west to northeast */
#define BENT_WtoSE 0x00010000L /* west to southeast */ #define BENT_WtoSE 0x00010000L /* west to southeast */
/* 90 degree corner-to-adjacent-corner lines */ /* 90 degree corner-to-adjacent-corner lines */
#define ANGLE_NEtoSE 0x00020000L /* northeast to southeast */ #define ANGLE_NEtoSE 0x00020000L /* northeast to southeast */
#define ANGLE_SEtoSW 0x00040000L /* southeast to southwest */ #define ANGLE_SEtoSW 0x00040000L /* southeast to southwest */
#define ANGLE_SWtoNW 0x00080000L /* southwest to northwest */ #define ANGLE_SWtoNW 0x00080000L /* southwest to northwest */
#define ANGLE_NWtoNE 0x00100000L /* northwest to northeast */ #define ANGLE_NWtoNE 0x00100000L /* northwest to northeast */
/* 45 degree angle side-to-near-corner lines */ /* 45 degree angle side-to-near-corner lines */
#define SHARP_NtoNE 0x00200000L /* north to northeast */ #define SHARP_NtoNE 0x00200000L /* north to northeast */
#define SHARP_EtoNE 0x00400000L /* east to northeast */ #define SHARP_EtoNE 0x00400000L /* east to northeast */
#define SHARP_EtoSE 0x00800000L /* east to southeast */ #define SHARP_EtoSE 0x00800000L /* east to southeast */
#define SHARP_StoSE 0x01000000L /* south to southeast */ #define SHARP_StoSE 0x01000000L /* south to southeast */
#define SHARP_StoSW 0x02000000L /* south to southwest */ #define SHARP_StoSW 0x02000000L /* south to southwest */
#define SHARP_WtoSW 0x04000000L /* west to southwest */ #define SHARP_WtoSW 0x04000000L /* west to southwest */
#define SHARP_WtoNW 0x08000000L /* west to northwest */ #define SHARP_WtoNW 0x08000000L /* west to northwest */
#define SHARP_NtoNW 0x10000000L /* north to northwest */ #define SHARP_NtoNW 0x10000000L /* north to northwest */
/* directions the cell can be reached from (point to previous cell) */ /* directions the cell can be reached from (point to previous cell) */
#define FROM_NOWHERE 0 #define FROM_NOWHERE 0
#define FROM_NORTH 1 #define FROM_NORTH 1
#define FROM_NORTHEAST 2 #define FROM_NORTHEAST 2
#define FROM_EAST 3 #define FROM_EAST 3
#define FROM_SOUTHEAST 4 #define FROM_SOUTHEAST 4
#define FROM_SOUTH 5 #define FROM_SOUTH 5
#define FROM_SOUTHWEST 6 #define FROM_SOUTHWEST 6
#define FROM_WEST 7 #define FROM_WEST 7
#define FROM_NORTHWEST 8 #define FROM_NORTHWEST 8
#define FROM_OTHERSIDE 9 #define FROM_OTHERSIDE 9
#endif // _CELL_H_ #endif // __AR_CELL_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
* 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 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __AR_MATRIX_H
#define __AR_MATRIX_H
#include <eda_rect.h>
#include <layers_id_colors_and_visibility.h>
class DRAWSEGMENT;
class TRACK;
class D_PAD;
class MODULE;
#define AR_MAX_ROUTING_LAYERS_COUNT 2
#define AR_SIDE_TOP 0
#define AR_SIDE_BOTTOM 1
/**
* class AR_MATRIX
* handle the matrix routing that describes the actual board
*/
class AR_MATRIX
{
public:
typedef unsigned char MATRIX_CELL;
typedef int DIST_CELL;
typedef char DIR_CELL;
MATRIX_CELL* m_BoardSide[AR_MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides
DIST_CELL* m_DistSide[AR_MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides:
// distance to cells
DIR_CELL* m_DirSide[AR_MAX_ROUTING_LAYERS_COUNT]; // the image map of 2 board sides:
// pointers back to source
bool m_InitMatrixDone;
int m_RoutingLayersCount; // Number of layers for autorouting (0 or 1)
int m_GridRouting; // Size of grid for autoplace/autoroute
EDA_RECT m_BrdBox; // Actual board bounding box
int m_Nrows, m_Ncols; // Matrix size
int m_MemSize; // Memory requirement, just for statistics
int m_RouteCount; // Number of routes
PCB_LAYER_ID m_routeLayerTop;
PCB_LAYER_ID m_routeLayerBottom;
private:
// a pointer to the current selected cell operation
void ( AR_MATRIX::*m_opWriteCell )( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
public:
enum CELL_OP
{
WRITE_CELL = 0,
WRITE_OR_CELL = 1,
WRITE_XOR_CELL = 2,
WRITE_AND_CELL = 3,
WRITE_ADD_CELL = 4
};
AR_MATRIX();
~AR_MATRIX();
void WriteCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell )
{
( *this.*m_opWriteCell )( aRow, aCol, aSide, aCell );
}
/**
* function GetBrdCoordOrigin
* @return the board coordinate corresponding to the
* routing matrix origin ( board coordinate offset )
*/
wxPoint GetBrdCoordOrigin()
{
return m_BrdBox.GetOrigin();
}
/**
* Function ComputeMatrixSize
* calculates the number of rows and columns of dimensions of \a aPcb for routing and
* automatic calculation of area.
* @param aPcb = the physical board
* @param aUseBoardEdgesOnly = true to use board edges only,
* = false to use the full board bounding box (default)
*/
bool ComputeMatrixSize( const EDA_RECT& aBoundingBox );
/**
* Function InitBoard
* initializes the data structures.
*
* @return the amount of memory used or -1 if default.
*/
int InitRoutingMatrix();
void UnInitRoutingMatrix();
// Initialize WriteCell to make the aLogicOp
void SetCellOperation( CELL_OP aLogicOp );
// functions to read/write one cell ( point on grid routing matrix:
MATRIX_CELL GetCell( int aRow, int aCol, int aSide );
void SetCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
void OrCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
void XorCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
void AndCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell );
DIST_CELL GetDist( int aRow, int aCol, int aSide );
void SetDist( int aRow, int aCol, int aSide, DIST_CELL );
int GetDir( int aRow, int aCol, int aSide );
void SetDir( int aRow, int aCol, int aSide, int aDir );
// calculate distance (with penalty) of a trace through a cell
int CalcDist( int x, int y, int z, int side );
// calculate approximate distance (manhattan distance)
int GetApxDist( int r1, int c1, int r2, int c2 );
void TraceSegmentPcb( DRAWSEGMENT* pt_segm, int color, int marge, AR_MATRIX::CELL_OP op_logic );
void TraceSegmentPcb( TRACK* aTrack, int color, int marge, AR_MATRIX::CELL_OP op_logic );
void CreateKeepOutRectangle(
int ux0, int uy0, int ux1, int uy1, int marge, int aKeepOut, LSET aLayerMask );
void PlacePad( D_PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic );
void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, double angle, LSET aLayerMask,
int color, AR_MATRIX::CELL_OP op_logic );
void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, LSET aLayerMask, int color,
AR_MATRIX::CELL_OP op_logic );
private:
void drawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color,
CELL_OP op_logic );
void traceCircle( int ux0, int uy0, int ux1, int uy1, int lg, LAYER_NUM layer, int color,
AR_MATRIX::CELL_OP op_logic );
void traceFilledCircle(
int cx, int cy, int radius, LSET aLayerMask, int color, AR_MATRIX::CELL_OP op_logic );
void traceArc( int ux0, int uy0, int ux1, int uy1, double ArcAngle, int lg, LAYER_NUM layer,
int color, AR_MATRIX::CELL_OP op_logic );
void tracePcbLine( int x0, int y0, int x1, int y1, LAYER_NUM layer, int color,
AR_MATRIX::CELL_OP op_logic );
};
#endif

View File

@ -0,0 +1,124 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <board_commit.h>
#include <class_draw_panel_gal.h>
#include <confirm.h>
#include <gal/graphics_abstraction_layer.h>
#include <preview_items/centreline_rect_item.h>
#include <preview_items/two_point_geom_manager.h>
#include <tool/tool_manager.h>
#include <view/view.h>
#include <view/view_controls.h>
// For frame ToolID values
#include <pcbnew_id.h>
// For action icons
#include <bitmaps.h>
#include <class_board_item.h>
#include <class_module.h>
#include <tools/pcb_actions.h>
#include <tools/selection_tool.h>
#include <tools/tool_event_utils.h>
#include <widgets/progress_reporter.h>
#include "ar_autoplacer.h"
#include "autoplacer_tool.h"
TOOL_ACTION PCB_ACTIONS::autoplaceSelectedComponents( "pcbnew.Autoplacer.autoplaceSelected",
AS_GLOBAL, 0, _( "Auto-place selected components" ),
_( "Performs automatic placement of selected components" ) );
TOOL_ACTION PCB_ACTIONS::autoplaceOffboardComponents( "pcbnew.Autoplacer.autoplaceOffboard",
AS_GLOBAL, 0, _( "Auto-place off-board components" ),
_( "Performs automatic placement of components outside board area" ) );
AUTOPLACE_TOOL::AUTOPLACE_TOOL() : PCB_TOOL( "pcbnew.Autoplacer" )
{
}
AUTOPLACE_TOOL::~AUTOPLACE_TOOL()
{
}
int AUTOPLACE_TOOL::autoplace( std::vector<MODULE*>& aModules, bool aPlaceOffboard )
{
auto overlay = view()->MakeOverlay();
Activate();
AR_AUTOPLACER autoplacer( board() );
BOARD_COMMIT commit( frame() );
autoplacer.SetOverlay( overlay );
std::unique_ptr<WX_PROGRESS_REPORTER> progressReporter(
new WX_PROGRESS_REPORTER( frame(), _( "Autoplace Components" ), 1 ) );
autoplacer.SetProgressReporter( progressReporter.get() );
auto result = autoplacer.AutoplaceModules( aModules, &commit, aPlaceOffboard );
if( result == AR_COMPLETED )
commit.Push( _( "Autoplace components" ) );
else
commit.Revert();
return 0;
}
int AUTOPLACE_TOOL::autoplaceSelected( const TOOL_EVENT& aEvent )
{
std::vector<MODULE*> mods;
for( auto item : selection() )
{
if( item->Type() == PCB_MODULE_T )
mods.push_back( static_cast<MODULE*>( item ) );
}
return autoplace( mods, false );
}
int AUTOPLACE_TOOL::autoplaceOffboard( const TOOL_EVENT& aEvent )
{
std::vector<MODULE*> mods;
return autoplace( mods, true );
}
void AUTOPLACE_TOOL::setTransitions()
{
Go( &AUTOPLACE_TOOL::autoplaceSelected, PCB_ACTIONS::autoplaceSelectedComponents.MakeEvent() );
Go( &AUTOPLACE_TOOL::autoplaceOffboard, PCB_ACTIONS::autoplaceOffboardComponents.MakeEvent() );
}

View File

@ -0,0 +1,52 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef TOOLS_AUTOPLACE_TOOL_H
#define TOOLS_AUTOPLACE_TOOL_H
#include <tools/pcb_tool.h>
/**
* Class AUTOPLACE_TOOL
*
* Tool responsible for automagic placement of components.
*/
class AUTOPLACE_TOOL : public PCB_TOOL
{
public:
AUTOPLACE_TOOL();
~AUTOPLACE_TOOL();
///> Bind handlers to corresponding TOOL_ACTIONs
void setTransitions() override;
private:
int autoplace( std::vector<MODULE*>& aModules, bool aPlaceOffboard );
int autoplaceSelected( const TOOL_EVENT& aEvent );
int autoplaceOffboard( const TOOL_EVENT& aEvent );
};
#endif // TOOLS_AUTOPLACE_TOOL_H

View File

@ -239,12 +239,12 @@ int CONNECTIVITY_DATA::countRelevantItems( const std::vector<BOARD_ITEM*>& aItem
case PCB_VIA_T: case PCB_VIA_T:
n++; n++;
break; break;
default: default:
break; break;
} }
} }
return n; return n;
} }
@ -261,7 +261,7 @@ void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>&
m_dynamicConnectivity->Build( aItems ); m_dynamicConnectivity->Build( aItems );
m_dynamicRatsnest.clear(); m_dynamicRatsnest.clear();
BlockRatsnestItems( aItems ); BlockRatsnestItems( aItems );
for( unsigned int nc = 1; nc < m_dynamicConnectivity->m_nets.size(); nc++ ) for( unsigned int nc = 1; nc < m_dynamicConnectivity->m_nets.size(); nc++ )
@ -659,8 +659,51 @@ void CONNECTIVITY_DATA::MarkItemNetAsDirty( BOARD_ITEM *aItem )
} }
} }
void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter ) void CONNECTIVITY_DATA::SetProgressReporter( PROGRESS_REPORTER* aReporter )
{ {
m_progressReporter = aReporter; m_progressReporter = aReporter;
m_connAlgo->SetProgressReporter( m_progressReporter ); m_connAlgo->SetProgressReporter( m_progressReporter );
} }
const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForComponent( MODULE* aComponent, bool aSkipInternalConnections )
{
std::set<int> nets;
std::set<D_PAD*> pads;
std::vector<CN_EDGE> edges;
for( auto pad : aComponent->Pads() )
{
nets.insert( pad->GetNetCode() );
pads.insert( pad );
}
for ( auto netcode : nets )
{
auto net = GetRatsnestForNet( netcode );
for ( auto edge : net->GetEdges() )
{
auto srcNode = edge.GetSourceNode();
auto dstNode = edge.GetTargetNode();
auto srcParent = static_cast<D_PAD*>( srcNode->Parent() );
auto dstParent = static_cast<D_PAD*>( dstNode->Parent() );
bool srcFound = ( pads.find(srcParent) != pads.end() );
bool dstFound = ( pads.find(dstParent) != pads.end() );
if ( srcFound && dstFound && !aSkipInternalConnections )
{
edges.push_back( edge );
}
else if ( srcFound || dstFound )
{
edges.push_back( edge );
}
}
}
return edges;
}

View File

@ -48,6 +48,7 @@ class RN_DATA;
class RN_NET; class RN_NET;
class TRACK; class TRACK;
class D_PAD; class D_PAD;
class MODULE;
class PROGRESS_REPORTER; class PROGRESS_REPORTER;
struct CN_DISJOINT_NET_ENTRY struct CN_DISJOINT_NET_ENTRY
@ -234,11 +235,11 @@ public:
} }
void MarkItemNetAsDirty( BOARD_ITEM* aItem ); void MarkItemNetAsDirty( BOARD_ITEM* aItem );
void SetProgressReporter( PROGRESS_REPORTER* aReporter ); void SetProgressReporter( PROGRESS_REPORTER* aReporter );
const std::vector<CN_EDGE> GetRatsnestForComponent( MODULE* aComponent, bool aSkipInternalConnections = false );
private: private:
int countRelevantItems( const std::vector<BOARD_ITEM*>& aItems ); int countRelevantItems( const std::vector<BOARD_ITEM*>& aItems );
void updateRatsnest(); void updateRatsnest();
void addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster ); void addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster );

View File

@ -156,10 +156,6 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
case ID_POPUP_PCB_MOVE_MODULE_REQUEST: case ID_POPUP_PCB_MOVE_MODULE_REQUEST:
case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST: case ID_POPUP_PCB_MOVE_TEXTMODULE_REQUEST:
case ID_POPUP_PCB_MOVE_PCB_TARGET_REQUEST: case ID_POPUP_PCB_MOVE_PCB_TARGET_REQUEST:
case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES:
case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE:
case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES:
case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE:
break; break;
case ID_POPUP_CANCEL_CURRENT_COMMAND: case ID_POPUP_CANCEL_CURRENT_COMMAND:
@ -1257,44 +1253,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
m_canvas->Refresh(); m_canvas->Refresh();
break; break;
case ID_POPUP_PCB_SPREAD_ALL_MODULES:
if( !IsOK( this,
_("Not locked footprints inside the board will be moved. OK?") ) )
break;
// Fall through
case ID_POPUP_PCB_SPREAD_NEW_MODULES:
if( GetBoard()->m_Modules == NULL )
{
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( &footprintList, id == ID_POPUP_PCB_SPREAD_NEW_MODULES,
true, GetCrossHairPosition() );
}
break;
case ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE:
LockModule( (MODULE*) GetScreen()->GetCurItem(), true );
break;
case ID_POPUP_PCB_AUTOPLACE_FREE_MODULE:
LockModule( (MODULE*) GetScreen()->GetCurItem(), false );
break;
case ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES:
LockModule( NULL, false );
break;
case ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES:
LockModule( NULL, true );
break;
default: default:
wxString msg; wxString msg;
msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ), id ); msg.Printf( wxT( "PCB_EDIT_FRAME::Process_Special_Functions() unknown event id %d" ), id );

View File

@ -337,6 +337,22 @@ void preparePlaceMenu( wxMenu* aParentMenu )
_( "&Grid Origin" ), _( "&Grid Origin" ),
_( "Set grid origin point" ), _( "Set grid origin point" ),
KiBitmap( grid_select_axis_xpm ) ); KiBitmap( grid_select_axis_xpm ) );
aParentMenu->AppendSeparator();
wxMenu* autoplaceSubmenu = new wxMenu;
AddMenuItem( autoplaceSubmenu, ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES,
_( "&Autoplace off-board components" ), _( "" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
);
AddMenuItem( autoplaceSubmenu, ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES,
_( "&Autoplace selected components" ), _( "" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
);
AddMenuItem( aParentMenu, autoplaceSubmenu,
-1, _( "&Auto-place" ),
_( "Automatic component placement" ), KiBitmap( grid_select_axis_xpm ) // fixme: icons
);
} }

View File

@ -394,17 +394,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
case ID_NO_TOOL_SELECTED: case ID_NO_TOOL_SELECTED:
{ {
wxMenu* commands = new wxMenu; wxMenu* commands = new wxMenu;
AddMenuItem( aPopMenu, commands, ID_POPUP_PCB_AUTOPLACE_COMMANDS,
_( "Global Spread and Place" ), KiBitmap( move_xpm ) );
AddMenuItem( commands, ID_POPUP_PCB_SPREAD_ALL_MODULES,
_( "Spread out All Footprints" ), KiBitmap( move_xpm ) );
commands->Append( ID_POPUP_PCB_SPREAD_NEW_MODULES,
_( "Spread out Footprints not Already on Board" ) );
AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES,
_( "Unlock All Footprints" ), KiBitmap( unlocked_xpm ) );
AddMenuItem( commands, ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES,
_( "Lock All Footprints" ), KiBitmap( locked_xpm ) );
if( !trackFound ) if( !trackFound )
{ {
msg = AddHotkeyName( _( "Begin Track" ), g_Board_Editor_Hotkeys_Descr, HK_ADD_NEW_TRACK ); msg = AddHotkeyName( _( "Begin Track" ), g_Board_Editor_Hotkeys_Descr, HK_ADD_NEW_TRACK );
@ -808,17 +798,9 @@ void PCB_EDIT_FRAME::createPopUpMenuForFootprints( MODULE* aModule, wxMenu* menu
if( !aModule->IsLocked() ) if( !aModule->IsLocked() )
{ {
msg = AddHotkeyName( _("Lock Footprint" ), g_Board_Editor_Hotkeys_Descr,
HK_LOCK_UNLOCK_FOOTPRINT );
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, msg,
KiBitmap( locked_xpm ) );
} }
else else
{ {
msg = AddHotkeyName( _( "Unlock Footprint" ), g_Board_Editor_Hotkeys_Descr,
HK_LOCK_UNLOCK_FOOTPRINT );
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, msg,
KiBitmap( unlocked_xpm ) );
} }
} }

View File

@ -256,12 +256,6 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
EVT_MENU( ID_POPUP_PCB_DELETE_TRACKSEG, PCB_EDIT_FRAME::Process_Special_Functions ) EVT_MENU( ID_POPUP_PCB_DELETE_TRACKSEG, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE, EVT_MENU_RANGE( ID_POPUP_GENERAL_START_RANGE, ID_POPUP_GENERAL_END_RANGE,
PCB_EDIT_FRAME::Process_Special_Functions ) PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_SPREAD_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_SPREAD_NEW_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES, PCB_EDIT_FRAME::Process_Special_Functions )
EVT_MENU( ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, PCB_EDIT_FRAME::Process_Special_Functions )
// User interface update event handlers. // User interface update event handlers.
EVT_UPDATE_UI( ID_SAVE_BOARD, PCB_EDIT_FRAME::OnUpdateSave ) EVT_UPDATE_UI( ID_SAVE_BOARD, PCB_EDIT_FRAME::OnUpdateSave )

View File

@ -250,28 +250,11 @@ enum pcbnew_ids
// reserve a block of MAX_ITEMS_IN_PICKER ids for the item selection popup // reserve a block of MAX_ITEMS_IN_PICKER ids for the item selection popup
ID_POPUP_PCB_ITEM_SELECTION_START, ID_POPUP_PCB_ITEM_SELECTION_START,
ID_POPUP_PCB_ITEM_SELECTION_END = MAX_ITEMS_IN_PICKER + ID_POPUP_PCB_ITEM_SELECTION_START, ID_POPUP_PCB_ITEM_SELECTION_END = MAX_ITEMS_IN_PICKER + ID_POPUP_PCB_ITEM_SELECTION_START,
ID_POPUP_PCB_AUTOPLACE_START_RANGE,
ID_POPUP_PCB_AUTOPLACE_FIXE_MODULE, ID_POPUP_PCB_SPREAD_SELECTED_MODULES,
ID_POPUP_PCB_AUTOPLACE_FREE_MODULE, ID_POPUP_PCB_SPREAD_OFF_BOARD_MODULES,
ID_POPUP_PCB_AUTOPLACE_FREE_ALL_MODULES, ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES,
ID_POPUP_PCB_AUTOPLACE_FIXE_ALL_MODULES, ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES,
ID_POPUP_PCB_AUTOPLACE_CURRENT_MODULE,
ID_POPUP_PCB_SPREAD_ALL_MODULES,
ID_POPUP_PCB_SPREAD_NEW_MODULES,
ID_POPUP_PCB_AUTOPLACE_COMMANDS,
ID_POPUP_PCB_AUTOPLACE_ALL_MODULES,
ID_POPUP_PCB_AUTOPLACE_NEW_MODULES,
ID_POPUP_PCB_AUTOPLACE_NEXT_MODULE,
ID_POPUP_PCB_AUTOROUTE_COMMANDS,
ID_POPUP_PCB_AUTOROUTE_ALL_MODULES,
ID_POPUP_PCB_AUTOROUTE_MODULE,
ID_POPUP_PCB_AUTOROUTE_PAD,
ID_POPUP_PCB_AUTOROUTE_NET,
ID_POPUP_PCB_AUTOROUTE_RESET_UNROUTED,
ID_POPUP_PCB_AUTOROUTE_SELECT_LAYERS,
ID_POPUP_PCB_AUTOPLACE_END_RANGE,
ID_MENU_READ_BOARD_BACKUP_FILE, ID_MENU_READ_BOARD_BACKUP_FILE,
ID_MENU_RECOVER_BOARD_AUTOSAVE, ID_MENU_RECOVER_BOARD_AUTOSAVE,

View File

@ -212,6 +212,13 @@ OPT<TOOL_EVENT> PCB_ACTIONS::TranslateLegacyId( int aId )
case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES: case ID_POPUP_PCB_REMOVE_FILLED_AREAS_IN_ALL_ZONES:
return PCB_ACTIONS::zoneUnfillAll.MakeEvent(); return PCB_ACTIONS::zoneUnfillAll.MakeEvent();
case ID_POPUP_PCB_AUTOPLACE_OFF_BOARD_MODULES:
return PCB_ACTIONS::autoplaceOffboardComponents.MakeEvent();
case ID_POPUP_PCB_AUTOPLACE_SELECTED_MODULES:
return PCB_ACTIONS::autoplaceSelectedComponents.MakeEvent();
} }
return OPT<TOOL_EVENT>(); return OPT<TOOL_EVENT>();

View File

@ -403,6 +403,8 @@ public:
static TOOL_ACTION editFootprintInFpEditor; static TOOL_ACTION editFootprintInFpEditor;
static TOOL_ACTION autoplaceOffboardComponents;
static TOOL_ACTION autoplaceSelectedComponents;
///> @copydoc COMMON_ACTIONS::TranslateLegacyId() ///> @copydoc COMMON_ACTIONS::TranslateLegacyId()
virtual OPT<TOOL_EVENT> TranslateLegacyId( int aId ) override; virtual OPT<TOOL_EVENT> TranslateLegacyId( int aId ) override;

View File

@ -45,6 +45,7 @@
#include <router/router_tool.h> #include <router/router_tool.h>
#include <router/length_tuner_tool.h> #include <router/length_tuner_tool.h>
#include <autorouter/autoplacer_tool.h>
void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager ) void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
{ {
@ -64,4 +65,5 @@ void PCB_ACTIONS::RegisterAllTools( TOOL_MANAGER* aToolManager )
aToolManager->RegisterTool( new MICROWAVE_TOOL ); aToolManager->RegisterTool( new MICROWAVE_TOOL );
aToolManager->RegisterTool( new POSITION_RELATIVE_TOOL ); aToolManager->RegisterTool( new POSITION_RELATIVE_TOOL );
aToolManager->RegisterTool( new ZONE_FILLER_TOOL ); aToolManager->RegisterTool( new ZONE_FILLER_TOOL );
aToolManager->RegisterTool( new AUTOPLACE_TOOL );
} }