50 changed files with 4706 additions and 2075 deletions
-
2common/draw_frame.cpp
-
24common/geometry/hetriang.cpp
-
2common/tool/action_manager.cpp
-
86demos/simulation/rectifier/rectifier.pro
-
446include/geometry/poly_grid_partition.h
-
1include/geometry/shape_line_chain.h
-
40include/profile.h
-
7include/ttl/halfedge/hedart.h
-
149include/ttl/halfedge/hetriang.h
-
2include/wxBasePcbFrame.h
-
2pcbnew/CMakeLists.txt
-
19pcbnew/board_commit.cpp
-
4pcbnew/board_netlist_updater.cpp
-
15pcbnew/class_board.cpp
-
14pcbnew/class_board.h
-
14pcbnew/class_board_connected_item.cpp
-
3pcbnew/class_board_connected_item.h
-
7pcbnew/class_zone.h
-
73pcbnew/connect.cpp
-
377pcbnew/connectivity.cpp
-
204pcbnew/connectivity.h
-
903pcbnew/connectivity_algo.cpp
-
926pcbnew/connectivity_algo.h
-
8pcbnew/deltrack.cpp
-
104pcbnew/dialogs/dialog_general_options_BoardEditor_base.fbp
-
2pcbnew/dialogs/dialog_global_deletion.cpp
-
8pcbnew/dialogs/dialog_netlist.cpp
-
24pcbnew/drc.cpp
-
2pcbnew/files.cpp
-
2pcbnew/loadcmp.cpp
-
2pcbnew/netlist.cpp
-
5pcbnew/pcb_draw_panel_gal.cpp
-
4pcbnew/pcbframe.cpp
-
2pcbnew/ratsnest.cpp
-
1510pcbnew/ratsnest_data.cpp
-
584pcbnew/ratsnest_data.h
-
88pcbnew/ratsnest_viewitem.cpp
-
7pcbnew/ratsnest_viewitem.h
-
809pcbnew/tools/common_actions.cpp
-
24pcbnew/tools/edit_tool.cpp
-
8pcbnew/tools/edit_tool.h
-
1pcbnew/tools/pcb_actions.h
-
88pcbnew/tools/pcb_editor_control.cpp
-
2pcbnew/tools/pcbnew_control.cpp
-
4pcbnew/tools/point_editor.cpp
-
30pcbnew/tools/selection_tool.cpp
-
23pcbnew/undo_redo.cpp
-
13pcbnew/zones_by_polygon_fill_functions.cpp
-
15pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp
-
72pcbnew/zones_polygons_insulated_copper_islands.cpp
@ -0,0 +1,446 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KICAD, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2016-2017 CERN |
||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> |
||||
|
* |
||||
|
* 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 __POLY_GRID_PARTITION_H |
||||
|
#define __POLY_GRID_PARTITION_H |
||||
|
|
||||
|
#include <geometry/seg.h> |
||||
|
#include <geometry/shape_line_chain.h> |
||||
|
|
||||
|
#include <vector> |
||||
|
#include <algorithm> |
||||
|
#include <unordered_map> |
||||
|
#include <set> |
||||
|
|
||||
|
/** |
||||
|
* Class POLY_GRID_PARTITION |
||||
|
* |
||||
|
* Provides a fast test for point inside polygon by splitting the edges |
||||
|
* of the polygon into a rectangular grid. |
||||
|
*/ |
||||
|
class POLY_GRID_PARTITION |
||||
|
{ |
||||
|
private: |
||||
|
enum HASH_FLAG |
||||
|
{ |
||||
|
LEAD_H = 1, |
||||
|
LEAD_V = 2, |
||||
|
TRAIL_H = 4, |
||||
|
TRAIL_V = 8 |
||||
|
}; |
||||
|
|
||||
|
using EDGE_LIST = std::vector<int>; |
||||
|
|
||||
|
template <class T> |
||||
|
inline void hash_combine( std::size_t& seed, const T& v ) |
||||
|
{ |
||||
|
std::hash<T> hasher; |
||||
|
seed ^= hasher( v ) + 0x9e3779b9 + (seed << 6) + (seed >> 2); |
||||
|
} |
||||
|
|
||||
|
struct segsEqual |
||||
|
{ |
||||
|
bool operator()( const SEG& a, const SEG& b ) const |
||||
|
{ |
||||
|
return (a.A == b.A && a.B == b.B) || (a.A == b.B && a.B == b.A); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
struct segHash |
||||
|
{ |
||||
|
std::size_t operator()( const SEG& a ) const |
||||
|
{ |
||||
|
std::size_t seed = 0; |
||||
|
|
||||
|
return a.A.x + a.B.x + a.A.y + a.B.y; |
||||
|
|
||||
|
return seed; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
const VECTOR2I grid2poly( const VECTOR2I& p ) const |
||||
|
{ |
||||
|
int px = rescale( p.x, m_bbox.GetWidth(), m_gridSize ) + m_bbox.GetPosition().x; |
||||
|
int py = rescale( p.y, m_bbox.GetHeight(), m_gridSize ) + m_bbox.GetPosition().y; // (int) floor( (double) p.y / m_gridSize * (double) m_bbox.GetHeight() + m_bbox.GetPosition().y ); |
||||
|
|
||||
|
return VECTOR2I( px, py ); |
||||
|
} |
||||
|
|
||||
|
int grid2polyX( int x ) const |
||||
|
{ |
||||
|
return rescale( x, m_bbox.GetWidth(), m_gridSize ) + m_bbox.GetPosition().x; |
||||
|
} |
||||
|
|
||||
|
int grid2polyY( int y ) const |
||||
|
{ |
||||
|
return rescale( y, m_bbox.GetHeight(), m_gridSize ) + m_bbox.GetPosition().y; |
||||
|
} |
||||
|
|
||||
|
const VECTOR2I poly2grid( const VECTOR2I& p ) const |
||||
|
{ |
||||
|
int px = rescale( p.x - m_bbox.GetPosition().x, m_gridSize, m_bbox.GetWidth() ); |
||||
|
int py = rescale( p.y - m_bbox.GetPosition().y, m_gridSize, m_bbox.GetHeight() ); |
||||
|
|
||||
|
if( px < 0 ) |
||||
|
px = 0; |
||||
|
|
||||
|
if( px >= m_gridSize ) |
||||
|
px = m_gridSize - 1; |
||||
|
|
||||
|
if( py < 0 ) |
||||
|
py = 0; |
||||
|
|
||||
|
if( py >= m_gridSize ) |
||||
|
py = m_gridSize - 1; |
||||
|
|
||||
|
return VECTOR2I( px, py ); |
||||
|
} |
||||
|
|
||||
|
int poly2gridX( int x ) const |
||||
|
{ |
||||
|
int px = rescale( x - m_bbox.GetPosition().x, m_gridSize, m_bbox.GetWidth() ); |
||||
|
|
||||
|
if( px < 0 ) |
||||
|
px = 0; |
||||
|
|
||||
|
if( px >= m_gridSize ) |
||||
|
px = m_gridSize - 1; |
||||
|
|
||||
|
return px; |
||||
|
} |
||||
|
|
||||
|
int poly2gridY( int y ) const |
||||
|
{ |
||||
|
int py = rescale( y - m_bbox.GetPosition().y, m_gridSize, m_bbox.GetHeight() ); |
||||
|
|
||||
|
if( py < 0 ) |
||||
|
py = 0; |
||||
|
|
||||
|
if( py >= m_gridSize ) |
||||
|
py = m_gridSize - 1; |
||||
|
|
||||
|
return py; |
||||
|
} |
||||
|
|
||||
|
void build( const SHAPE_LINE_CHAIN& aPolyOutline, int gridSize ) |
||||
|
{ |
||||
|
m_outline = aPolyOutline; |
||||
|
m_bbox = m_outline.BBox(); |
||||
|
m_gridSize = gridSize; |
||||
|
|
||||
|
m_outline.SetClosed( true ); |
||||
|
|
||||
|
m_grid.reserve( gridSize * gridSize ); |
||||
|
|
||||
|
for( int y = 0; y < gridSize; y++ ) |
||||
|
{ |
||||
|
for( int x = 0; x < gridSize; x++ ) |
||||
|
{ |
||||
|
m_grid.push_back( EDGE_LIST() ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
VECTOR2I ref_v( 0, 1 ); |
||||
|
VECTOR2I ref_h( 0, 1 ); |
||||
|
|
||||
|
m_flags.reserve( m_outline.SegmentCount() ); |
||||
|
|
||||
|
std::unordered_map<SEG, int, segHash, segsEqual> edgeSet; |
||||
|
|
||||
|
for( int i = 0; i<m_outline.SegmentCount(); i++ ) |
||||
|
{ |
||||
|
SEG edge = m_outline.CSegment( i ); |
||||
|
|
||||
|
if( edgeSet.find( edge ) == edgeSet.end() ) |
||||
|
{ |
||||
|
edgeSet[edge] = 1; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
edgeSet[edge]++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for( int i = 0; i<m_outline.SegmentCount(); i++ ) |
||||
|
{ |
||||
|
auto edge = m_outline.CSegment( i ); |
||||
|
auto dir = edge.B - edge.A; |
||||
|
int flags = 0; |
||||
|
|
||||
|
if( edgeSet[edge] == 1 ) |
||||
|
{ |
||||
|
if( dir.Dot( ref_h ) > 0 ) |
||||
|
{ |
||||
|
flags |= LEAD_H; |
||||
|
} |
||||
|
else if( dir.Dot( ref_h ) < 0 ) |
||||
|
{ |
||||
|
flags |= TRAIL_H; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
m_flags.push_back( flags ); |
||||
|
|
||||
|
if( !flags ) |
||||
|
continue; |
||||
|
|
||||
|
std::set<int> indices; |
||||
|
|
||||
|
indices.insert( m_gridSize * poly2gridY( edge.A.y ) + poly2gridX( edge.A.x ) ); |
||||
|
indices.insert( m_gridSize * poly2gridY( edge.B.y ) + poly2gridX( edge.B.x ) ); |
||||
|
|
||||
|
if( edge.A.x > edge.B.x ) |
||||
|
std::swap( edge.A, edge.B ); |
||||
|
|
||||
|
dir = edge.B - edge.A; |
||||
|
|
||||
|
if( dir.x != 0 ) |
||||
|
{ |
||||
|
int gx0 = poly2gridX( edge.A.x ) + 1; |
||||
|
int gx1 = poly2gridX( edge.B.x ); |
||||
|
|
||||
|
for( int x = gx0; x <= gx1; x++ ) |
||||
|
{ |
||||
|
int px = grid2polyX( x ); |
||||
|
int py = ( edge.A.y + rescale( dir.y, px - edge.A.x, dir.x ) ); |
||||
|
int yy = poly2gridY( py ); |
||||
|
|
||||
|
indices.insert( m_gridSize * yy + x ); |
||||
|
|
||||
|
if( x > 0 ) |
||||
|
indices.insert( m_gridSize * yy + x - 1 ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if( edge.A.y > edge.B.y ) |
||||
|
std::swap( edge.A, edge.B ); |
||||
|
|
||||
|
dir = edge.B - edge.A; |
||||
|
|
||||
|
if( dir.y != 0 ) |
||||
|
{ |
||||
|
int gy0 = poly2gridY( edge.A.y ) + 1; |
||||
|
int gy1 = poly2gridY( edge.B.y ); |
||||
|
|
||||
|
for( int y = gy0; y <= gy1; y++ ) |
||||
|
{ |
||||
|
int py = grid2polyY( y ); |
||||
|
int px = ( edge.A.x + rescale( dir.x, py - edge.A.y, dir.y ) ); |
||||
|
int xx = poly2gridX( px ); |
||||
|
|
||||
|
indices.insert( m_gridSize * y + xx ); |
||||
|
|
||||
|
if( y > 0 ) |
||||
|
indices.insert( m_gridSize * (y - 1) + xx ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for( auto idx : indices ) |
||||
|
m_grid[idx].push_back( i ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool inRange( int v1, int v2, int x ) const |
||||
|
{ |
||||
|
if( v1 < v2 ) |
||||
|
{ |
||||
|
return x >= v1 && x <= v2; |
||||
|
} |
||||
|
|
||||
|
return x >= v2 && x <= v1; |
||||
|
} |
||||
|
|
||||
|
struct SCAN_STATE |
||||
|
{ |
||||
|
SCAN_STATE() |
||||
|
{ |
||||
|
dist_max = INT_MAX; |
||||
|
nearest = -1; |
||||
|
nearest_prev = -1; |
||||
|
}; |
||||
|
|
||||
|
int dist_prev; |
||||
|
int dist_max; |
||||
|
int nearest_prev; |
||||
|
int nearest; |
||||
|
}; |
||||
|
|
||||
|
void scanCell( SCAN_STATE& state, const EDGE_LIST& cell, const VECTOR2I& aP ) const |
||||
|
{ |
||||
|
for( auto index : cell ) |
||||
|
{ |
||||
|
const SEG& edge = m_outline.CSegment( index ); |
||||
|
|
||||
|
if( edge.A.y == edge.B.y ) // horizontal edge |
||||
|
continue; |
||||
|
|
||||
|
if( m_flags[index] == 0 ) // a slit |
||||
|
continue; |
||||
|
|
||||
|
if( inRange( edge.A.y, edge.B.y, aP.y ) ) |
||||
|
{ |
||||
|
int dist = 0; |
||||
|
|
||||
|
if( edge.A.y == aP.y ) |
||||
|
{ |
||||
|
dist = -(aP.x - edge.A.x); |
||||
|
} |
||||
|
else if( edge.B.y == aP.y ) |
||||
|
{ |
||||
|
dist = -(aP.x - edge.B.x); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
const VECTOR2I e( edge.B - edge.A ); |
||||
|
const VECTOR2I ff( 1, 0 ); |
||||
|
const VECTOR2I ac( aP - edge.A ); |
||||
|
|
||||
|
auto d = ff.Cross( e ); |
||||
|
auto q = e.Cross( ac ); |
||||
|
|
||||
|
using ecoord = VECTOR2I::extended_type; |
||||
|
|
||||
|
dist = rescale( q, (ecoord) 1, d ); |
||||
|
} |
||||
|
|
||||
|
if( dist == 0 ) |
||||
|
{ |
||||
|
if( state.nearest_prev < 0 || state.nearest != index ) |
||||
|
{ |
||||
|
state.dist_prev = state.dist_max; |
||||
|
state.nearest_prev = state.nearest; |
||||
|
} |
||||
|
|
||||
|
state.nearest = index; |
||||
|
state.dist_max = 0; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if( dist != 0 && std::abs( dist ) <= std::abs( state.dist_max ) ) |
||||
|
{ |
||||
|
if( state.nearest_prev < 0 || state.nearest != index ) |
||||
|
{ |
||||
|
state.dist_prev = state.dist_max; |
||||
|
state.nearest_prev = state.nearest; |
||||
|
} |
||||
|
|
||||
|
state.dist_max = dist; |
||||
|
state.nearest = index; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
POLY_GRID_PARTITION( const SHAPE_LINE_CHAIN& aPolyOutline, int gridSize ) |
||||
|
{ |
||||
|
build( aPolyOutline, gridSize ); |
||||
|
} |
||||
|
|
||||
|
int ContainsPoint( const VECTOR2I& aP ) // const |
||||
|
{ |
||||
|
const auto gridPoint = poly2grid( aP ); |
||||
|
|
||||
|
if( !m_bbox.Contains( aP ) ) |
||||
|
return false; |
||||
|
|
||||
|
SCAN_STATE state; |
||||
|
const EDGE_LIST& cell = m_grid[ m_gridSize * gridPoint.y + gridPoint.x ]; |
||||
|
|
||||
|
scanCell( state, cell, aP ); |
||||
|
|
||||
|
if( state.nearest < 0 ) |
||||
|
{ |
||||
|
state = SCAN_STATE(); |
||||
|
|
||||
|
for( int d = 1; d <= m_gridSize; d++ ) |
||||
|
{ |
||||
|
int xl = gridPoint.x - d; |
||||
|
int xh = gridPoint.x + d; |
||||
|
|
||||
|
if( xl >= 0 ) |
||||
|
{ |
||||
|
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xl ]; |
||||
|
scanCell( state, cell2, aP ); |
||||
|
|
||||
|
if( state.nearest >= 0 ) |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if( xh < m_gridSize ) |
||||
|
{ |
||||
|
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xh ]; |
||||
|
scanCell( state, cell2, aP ); |
||||
|
|
||||
|
if( state.nearest >= 0 ) |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if( state.nearest < 0 ) |
||||
|
return 0; |
||||
|
|
||||
|
if( state.dist_max == 0 ) |
||||
|
return 1; |
||||
|
|
||||
|
if( state.nearest_prev >= 0 && state.dist_max == state.dist_prev ) |
||||
|
{ |
||||
|
int d = std::abs( state.nearest_prev - state.nearest ); |
||||
|
|
||||
|
if( (d == 1) && ( (m_flags[state.nearest_prev] & m_flags[state.nearest]) == 0 ) ) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
else if( d > 1 ) |
||||
|
{ |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if( state.dist_max > 0 ) |
||||
|
{ |
||||
|
return m_flags[state.nearest] & LEAD_H ? 1 : 0; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return m_flags[state.nearest] & TRAIL_H ? 1 : 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const BOX2I& BBox() const |
||||
|
{ |
||||
|
return m_bbox; |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
int m_gridSize; |
||||
|
SHAPE_LINE_CHAIN m_outline; |
||||
|
BOX2I m_bbox; |
||||
|
std::vector<int> m_flags; |
||||
|
std::vector<EDGE_LIST> m_grid; |
||||
|
}; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,377 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KICAD, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2017 CERN |
||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> |
||||
|
* |
||||
|
* 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 |
||||
|
*/ |
||||
|
#define PROFILE
|
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
#include <profile.h>
|
||||
|
#endif
|
||||
|
|
||||
|
#include <connectivity.h>
|
||||
|
#include <connectivity_algo.h>
|
||||
|
#include <ratsnest_data.h>
|
||||
|
|
||||
|
#ifdef USE_OPENMP
|
||||
|
#include <omp.h>
|
||||
|
#endif /* USE_OPENMP */
|
||||
|
|
||||
|
CONNECTIVITY_DATA::CONNECTIVITY_DATA() |
||||
|
{ |
||||
|
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
CONNECTIVITY_DATA::~CONNECTIVITY_DATA() |
||||
|
{ |
||||
|
Clear(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CONNECTIVITY_DATA::Add( BOARD_ITEM* aItem ) |
||||
|
{ |
||||
|
m_connAlgo->Add( aItem ); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CONNECTIVITY_DATA::Remove( BOARD_ITEM* aItem ) |
||||
|
{ |
||||
|
m_connAlgo->Remove( aItem ); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Function Update() |
||||
|
* Updates the connectivity data for an item. |
||||
|
* @param aItem is an item to be updated. |
||||
|
* @return True if operation succeeded. The item will not be updated if it was not previously |
||||
|
* added to the ratsnest. |
||||
|
*/ |
||||
|
bool CONNECTIVITY_DATA::Update( BOARD_ITEM* aItem ) |
||||
|
{ |
||||
|
m_connAlgo->Remove( aItem ); |
||||
|
m_connAlgo->Add( aItem ); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::Build( BOARD* aBoard ) |
||||
|
{ |
||||
|
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO ); |
||||
|
m_connAlgo->Build( aBoard ); |
||||
|
|
||||
|
RecalculateRatsnest(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::Build( const std::vector<BOARD_ITEM*>& aItems ) |
||||
|
{ |
||||
|
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO ); |
||||
|
m_connAlgo->Build( aItems ); |
||||
|
|
||||
|
RecalculateRatsnest(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::updateRatsnest() |
||||
|
{ |
||||
|
int lastNet = m_connAlgo->NetCount(); |
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
PROF_COUNTER rnUpdate( "update-ratsnest" ); |
||||
|
#endif
|
||||
|
|
||||
|
int nDirty = 0; |
||||
|
|
||||
|
int i; |
||||
|
|
||||
|
#ifdef USE_OPENMP
|
||||
|
#pragma omp parallel shared(lastNet) private(i)
|
||||
|
{ |
||||
|
#pragma omp for schedule(guided, 1)
|
||||
|
#else /* USE_OPENMP */
|
||||
|
{ |
||||
|
#endif
|
||||
|
|
||||
|
// Start with net number 1, as 0 stands for not connected
|
||||
|
for( i = 1; i < lastNet; ++i ) |
||||
|
{ |
||||
|
if( m_nets[i]->IsDirty() ) |
||||
|
{ |
||||
|
m_nets[i]->Update(); |
||||
|
nDirty++; |
||||
|
} |
||||
|
} |
||||
|
} /* end of parallel section */ |
||||
|
#ifdef PROFILE
|
||||
|
rnUpdate.Show(); |
||||
|
#endif /* PROFILE */
|
||||
|
printf( "Dirty: %d\n", nDirty ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::addRatsnestCluster( std::shared_ptr<CN_CLUSTER> aCluster ) |
||||
|
{ |
||||
|
auto rnNet = m_nets[ aCluster->OriginNet() ]; |
||||
|
|
||||
|
rnNet->AddCluster( aCluster ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::RecalculateRatsnest() |
||||
|
{ |
||||
|
int lastNet = m_connAlgo->NetCount(); |
||||
|
|
||||
|
if( lastNet >= (int) m_nets.size() ) |
||||
|
{ |
||||
|
unsigned int prevSize = m_nets.size(); |
||||
|
m_nets.resize( lastNet + 1 ); |
||||
|
|
||||
|
for( unsigned int i = prevSize; i < m_nets.size(); i++ ) |
||||
|
m_nets[i] = new RN_NET; |
||||
|
} |
||||
|
|
||||
|
auto clusters = m_connAlgo->GetClusters(); |
||||
|
|
||||
|
int dirtyNets = 0; |
||||
|
|
||||
|
for( int net = 0; net < lastNet; net++ ) |
||||
|
if( m_connAlgo->IsNetDirty( net ) ) |
||||
|
{ |
||||
|
m_nets[net]->Clear(); |
||||
|
dirtyNets++; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
for( auto c : clusters ) |
||||
|
{ |
||||
|
int net = c->OriginNet(); |
||||
|
|
||||
|
if( m_connAlgo->IsNetDirty( net ) ) |
||||
|
{ |
||||
|
addRatsnestCluster( c ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
m_connAlgo->ClearDirtyFlags(); |
||||
|
|
||||
|
updateRatsnest(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::blockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems ) |
||||
|
{ |
||||
|
std::vector<BOARD_CONNECTED_ITEM*> citems; |
||||
|
|
||||
|
for( auto item : aItems ) |
||||
|
{ |
||||
|
if( item->Type() == PCB_MODULE_T ) |
||||
|
{ |
||||
|
for( auto pad : static_cast<MODULE*>(item)->PadsIter() ) |
||||
|
citems.push_back( pad ); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
citems.push_back( static_cast<BOARD_CONNECTED_ITEM*>(item) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for( auto item : citems ) |
||||
|
{ |
||||
|
auto& entry = m_connAlgo->ItemEntry( item ); |
||||
|
|
||||
|
for( auto cnItem : entry.GetItems() ) |
||||
|
{ |
||||
|
for( auto anchor : cnItem->Anchors() ) |
||||
|
anchor->SetNoLine( true ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
int CONNECTIVITY_DATA::GetNetCount() const |
||||
|
{ |
||||
|
return m_connAlgo->NetCount(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, |
||||
|
std::vector<int>& aIslands ) |
||||
|
{ |
||||
|
m_connAlgo->FindIsolatedCopperIslands( aZone, aIslands ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>& aItems ) |
||||
|
{ |
||||
|
m_dynamicConnectivity.reset( new CONNECTIVITY_DATA ); |
||||
|
m_dynamicConnectivity->Build( aItems ); |
||||
|
|
||||
|
m_dynamicRatsnest.clear(); |
||||
|
|
||||
|
blockRatsnestItems( aItems ); |
||||
|
|
||||
|
for( unsigned int nc = 1; nc < m_dynamicConnectivity->m_nets.size(); nc++ ) |
||||
|
{ |
||||
|
auto dynNet = m_dynamicConnectivity->m_nets[nc]; |
||||
|
|
||||
|
if( dynNet->GetNodeCount() != 0 ) |
||||
|
{ |
||||
|
auto ourNet = m_nets[nc]; |
||||
|
CN_ANCHOR_PTR nodeA, nodeB; |
||||
|
|
||||
|
if( ourNet->NearestBicoloredPair( *dynNet, nodeA, nodeB ) ) |
||||
|
{ |
||||
|
RN_DYNAMIC_LINE l; |
||||
|
l.a = nodeA->Pos(); |
||||
|
l.b = nodeB->Pos(); |
||||
|
l.netCode = nc; |
||||
|
|
||||
|
m_dynamicRatsnest.push_back( l ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for( auto net : m_dynamicConnectivity->m_nets ) |
||||
|
{ |
||||
|
if( !net ) |
||||
|
continue; |
||||
|
|
||||
|
const auto& edges = net->GetUnconnected(); |
||||
|
|
||||
|
if( edges.empty() ) |
||||
|
continue; |
||||
|
|
||||
|
for( const auto& edge : edges ) |
||||
|
{ |
||||
|
const auto& nodeA = edge.GetSourceNode(); |
||||
|
const auto& nodeB = edge.GetTargetNode(); |
||||
|
RN_DYNAMIC_LINE l; |
||||
|
|
||||
|
l.a = nodeA->Pos(); |
||||
|
l.b = nodeB->Pos(); |
||||
|
l.netCode = 0; |
||||
|
m_dynamicRatsnest.push_back( l ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const std::vector<RN_DYNAMIC_LINE>& CONNECTIVITY_DATA::GetDynamicRatsnest() const |
||||
|
{ |
||||
|
return m_dynamicRatsnest; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::ClearDynamicRatsnest() |
||||
|
{ |
||||
|
m_dynamicConnectivity.reset(); |
||||
|
m_dynamicRatsnest.clear(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::PropagateNets() |
||||
|
{ |
||||
|
m_connAlgo->PropagateNets(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
unsigned int CONNECTIVITY_DATA::GetUnconnectedCount() const |
||||
|
{ |
||||
|
unsigned int unconnected = 0; |
||||
|
|
||||
|
for( auto net : m_nets ) |
||||
|
{ |
||||
|
if( !net ) |
||||
|
continue; |
||||
|
|
||||
|
const auto& edges = net->GetUnconnected(); |
||||
|
|
||||
|
if( edges.empty() ) |
||||
|
continue; |
||||
|
|
||||
|
unconnected += edges.size(); |
||||
|
} |
||||
|
|
||||
|
return unconnected; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CONNECTIVITY_DATA::Clear() |
||||
|
{ |
||||
|
for( auto net : m_nets ) |
||||
|
delete net; |
||||
|
|
||||
|
m_nets.clear(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetConnectedItems( |
||||
|
const BOARD_CONNECTED_ITEM* aItem, |
||||
|
const KICAD_T aTypes[] ) const |
||||
|
{ |
||||
|
std::list<BOARD_CONNECTED_ITEM*> rv; |
||||
|
const auto clusters = m_connAlgo->SearchClusters( CN_CONNECTIVITY_ALGO::CSM_CONNECTIVITY_CHECK, aTypes, aItem->GetNetCode() ); |
||||
|
|
||||
|
for ( auto cl : clusters ) |
||||
|
if ( cl->Contains (aItem ) ) |
||||
|
{ |
||||
|
for ( const auto item : *cl ) |
||||
|
rv.push_back( item->Parent() ); |
||||
|
} |
||||
|
|
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const std::list<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems( |
||||
|
int aNetCode, |
||||
|
const KICAD_T aTypes[] ) const |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
bool CONNECTIVITY_DATA::CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport ) |
||||
|
{ |
||||
|
RecalculateRatsnest(); |
||||
|
|
||||
|
for ( auto net : m_nets ) |
||||
|
{ |
||||
|
if ( net ) |
||||
|
{ |
||||
|
for ( const auto& edge: net->GetEdges() ) |
||||
|
{ |
||||
|
CN_DISJOINT_NET_ENTRY ent; |
||||
|
ent.net = edge.GetSourceNode()->Parent()->GetNetCode(); |
||||
|
ent.a = edge.GetSourceNode()->Parent(); |
||||
|
ent.b = edge.GetTargetNode()->Parent(); |
||||
|
ent.anchorA = edge.GetSourceNode()->Pos(); |
||||
|
ent.anchorB = edge.GetTargetNode()->Pos(); |
||||
|
aReport.push_back( ent ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return aReport.empty(); |
||||
|
} |
||||
@ -0,0 +1,204 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KICAD, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2013-2017 CERN |
||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch> |
||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> |
||||
|
* |
||||
|
* 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 __CONNECTIVITY_H |
||||
|
#define __CONNECTIVITY_H |
||||
|
|
||||
|
#include <core/typeinfo.h> |
||||
|
|
||||
|
#include <wx/string.h> |
||||
|
#include <vector> |
||||
|
#include <list> |
||||
|
#include <memory> |
||||
|
|
||||
|
#include <math/vector2d.h> |
||||
|
|
||||
|
class CN_ITEM; |
||||
|
class CN_CLUSTER; |
||||
|
class CN_CONNECTIVITY_ALGO; |
||||
|
class BOARD; |
||||
|
class BOARD_CONNECTED_ITEM; |
||||
|
class BOARD_ITEM; |
||||
|
class ZONE_CONTAINER; |
||||
|
class RN_DATA; |
||||
|
class RN_NET; |
||||
|
|
||||
|
struct CN_DISJOINT_NET_ENTRY |
||||
|
{ |
||||
|
int net; |
||||
|
BOARD_CONNECTED_ITEM* a, * b; |
||||
|
VECTOR2I anchorA, anchorB; |
||||
|
}; |
||||
|
|
||||
|
struct RN_DYNAMIC_LINE |
||||
|
{ |
||||
|
int netCode; |
||||
|
VECTOR2I a, b; |
||||
|
}; |
||||
|
|
||||
|
// a wrapper class encompassing the connectivity computation algorithm and the |
||||
|
class CONNECTIVITY_DATA |
||||
|
{ |
||||
|
public: |
||||
|
CONNECTIVITY_DATA(); |
||||
|
~CONNECTIVITY_DATA(); |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Function Build() |
||||
|
* Builds the connectivity database for the board aBoard. |
||||
|
*/ |
||||
|
void Build( BOARD* aBoard ); |
||||
|
|
||||
|
/** |
||||
|
* Function Build() |
||||
|
* Builds the connectivity database for a set of items aItems. |
||||
|
*/ |
||||
|
void Build( const std::vector<BOARD_ITEM*>& aItems ); |
||||
|
|
||||
|
/** |
||||
|
* Function Add() |
||||
|
* Adds an item to the connectivity data. |
||||
|
* @param aItem is an item to be added. |
||||
|
* @return True if operation succeeded. |
||||
|
*/ |
||||
|
bool Add( BOARD_ITEM* aItem ); |
||||
|
|
||||
|
/** |
||||
|
* Function Remove() |
||||
|
* Removes an item from the connectivity data. |
||||
|
* @param aItem is an item to be updated. |
||||
|
* @return True if operation succeeded. |
||||
|
*/ |
||||
|
bool Remove( BOARD_ITEM* aItem ); |
||||
|
|
||||
|
/** |
||||
|
* Function Update() |
||||
|
* Updates the connectivity data for an item. |
||||
|
* @param aItem is an item to be updated. |
||||
|
* @return True if operation succeeded. |
||||
|
*/ |
||||
|
bool Update( BOARD_ITEM* aItem ); |
||||
|
|
||||
|
/** |
||||
|
* Function Clear() |
||||
|
* Erases the connectivity database. |
||||
|
*/ |
||||
|
|
||||
|
void Clear(); |
||||
|
|
||||
|
/** |
||||
|
* Function GetNetCount() |
||||
|
* Returns the total number of nets in the connectivity database. |
||||
|
*/ |
||||
|
int GetNetCount() const; |
||||
|
|
||||
|
/** |
||||
|
* Function GetRatsnestForNet() |
||||
|
* Returns the ratsnest, expressed as a set of graph edges for a given net. |
||||
|
*/ |
||||
|
RN_NET* GetRatsnestForNet( int aNet ) |
||||
|
{ |
||||
|
return m_nets[aNet]; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Function PropagateNets() |
||||
|
* Propagates the net codes from the source pads to the tracks/vias. |
||||
|
*/ |
||||
|
void PropagateNets(); |
||||
|
|
||||
|
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport ); |
||||
|
|
||||
|
/** |
||||
|
* Function FindIsolatedCopperIslands() |
||||
|
* Searches for copper islands in zone aZone that are not connected to any pad. |
||||
|
* @param aZone zone to test |
||||
|
* @param aIslands list of islands that have no connections (outline indices in the polygon set) |
||||
|
*/ |
||||
|
void FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands ); |
||||
|
|
||||
|
/** |
||||
|
* Function RecalculateRatsnest() |
||||
|
* Updates the ratsnest for the board. |
||||
|
*/ |
||||
|
void RecalculateRatsnest(); |
||||
|
|
||||
|
/** |
||||
|
* Function GetUnconnectedCount() |
||||
|
* Returns the number of remaining edges in the ratsnest. |
||||
|
*/ |
||||
|
unsigned int GetUnconnectedCount() const; |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* Function ClearDynamicRatsnest() |
||||
|
* Erases the temporary dynamic ratsnest (i.e. the ratsnest lines that) |
||||
|
* pcbnew displays when moving an item/set of items |
||||
|
*/ |
||||
|
void ClearDynamicRatsnest(); |
||||
|
|
||||
|
/** |
||||
|
* Function ComputeDynamicRatsnest() |
||||
|
* Calculates the temporary dynamic ratsnest (i.e. the ratsnest lines that) |
||||
|
* for the set of items aItems. |
||||
|
*/ |
||||
|
void ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>& aItems ); |
||||
|
|
||||
|
|
||||
|
const std::vector<RN_DYNAMIC_LINE>& GetDynamicRatsnest() const; |
||||
|
|
||||
|
/** |
||||
|
* Function GetConnectedItems() |
||||
|
* Returns a list of items connected to a source item aItem. |
||||
|
* @param aItem is the reference item to find other connected items. |
||||
|
* @param aTypes allows to filter by item types. |
||||
|
*/ |
||||
|
const std::list<BOARD_CONNECTED_ITEM*> GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem, |
||||
|
const KICAD_T aTypes[] ) const; |
||||
|
|
||||
|
/** |
||||
|
* Function GetNetItems() |
||||
|
* Returns the list of items that belong to a certain net. |
||||
|
* @param aNetCode is the net code. |
||||
|
* @param aTypes allows to filter by item types. |
||||
|
*/ |
||||
|
const std::list<BOARD_CONNECTED_ITEM*> GetNetItems( int aNetCode, |
||||
|
const KICAD_T aTypes[] ) const; |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
void updateRatsnest(); |
||||
|
void addRatsnestCluster( std::shared_ptr<CN_CLUSTER> aCluster ); |
||||
|
void blockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems ); |
||||
|
|
||||
|
std::unique_ptr<CONNECTIVITY_DATA> m_dynamicConnectivity; |
||||
|
std::shared_ptr<CN_CONNECTIVITY_ALGO> m_connAlgo; |
||||
|
|
||||
|
std::vector<RN_DYNAMIC_LINE> m_dynamicRatsnest; |
||||
|
std::vector<RN_NET*> m_nets; |
||||
|
}; |
||||
|
|
||||
|
#endif |
||||
@ -0,0 +1,903 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KICAD, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2016-2017 CERN |
||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> |
||||
|
* |
||||
|
* 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 <connectivity_algo.h>
|
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
#include <profile.h>
|
||||
|
#endif
|
||||
|
|
||||
|
bool operator<( const CN_ANCHOR_PTR a, const CN_ANCHOR_PTR b ) |
||||
|
{ |
||||
|
if( a->Pos().x == b->Pos().x ) |
||||
|
return a->Pos().y < b->Pos().y; |
||||
|
else |
||||
|
return a->Pos().x < b->Pos().x; |
||||
|
} |
||||
|
|
||||
|
bool CN_ANCHOR::IsDirty() const |
||||
|
{ |
||||
|
return m_item->Dirty(); |
||||
|
} |
||||
|
|
||||
|
CN_CLUSTER::CN_CLUSTER() |
||||
|
{ |
||||
|
m_items.reserve( 64 ); |
||||
|
m_originPad = nullptr; |
||||
|
m_originNet = -1; |
||||
|
m_conflicting = false; |
||||
|
} |
||||
|
|
||||
|
CN_CLUSTER::~CN_CLUSTER() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
wxString CN_CLUSTER::OriginNetName() const |
||||
|
{ |
||||
|
if( !m_originPad ) |
||||
|
return "<none>"; |
||||
|
else |
||||
|
return m_originPad->Parent()->GetNetname(); |
||||
|
} |
||||
|
|
||||
|
bool CN_CLUSTER::Contains( const CN_ITEM* aItem ) |
||||
|
{ |
||||
|
return std::find( m_items.begin(), m_items.end(), aItem ) != m_items.end(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CN_CLUSTER::Contains( const BOARD_CONNECTED_ITEM* aItem ) |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
if( item->Parent() == aItem ) |
||||
|
return true; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
void CN_ITEM::Dump() |
||||
|
{ |
||||
|
printf(" valid: %d, connected: \n", !!Valid()); |
||||
|
for(auto i : m_connected ) |
||||
|
{ |
||||
|
TRACK *t = static_cast<TRACK*>(i->Parent()); |
||||
|
printf(" - %p %d\n", t, t->Type() ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void CN_CLUSTER::Dump() |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
{ |
||||
|
wxLogTrace( "CN", " - item : %p bitem : %p type : %d inet %s\n", item, item->Parent(), |
||||
|
item->Parent()->Type(), (const char*) item->Parent()->GetNetname().c_str() ); |
||||
|
printf( "- item : %p bitem : %p type : %d inet %s\n", item, item->Parent(), |
||||
|
item->Parent()->Type(), (const char*) item->Parent()->GetNetname().c_str() ); |
||||
|
item->Dump(); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void CN_CLUSTER::Add( CN_ITEM* item ) |
||||
|
{ |
||||
|
|
||||
|
m_items.push_back( item ); |
||||
|
|
||||
|
if ( m_originNet < 0 ) |
||||
|
{ |
||||
|
m_originNet = item->Net(); |
||||
|
} |
||||
|
|
||||
|
if( item->Parent()->Type() == PCB_PAD_T ) |
||||
|
{ |
||||
|
if( !m_originPad ) |
||||
|
{ |
||||
|
m_originPad = item; |
||||
|
m_originNet = item->Net(); |
||||
|
} |
||||
|
if( m_originPad && item->Net() != m_originNet ) |
||||
|
{ |
||||
|
m_conflicting = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
CN_CONNECTIVITY_ALGO::CN_CONNECTIVITY_ALGO() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
CN_CONNECTIVITY_ALGO::~CN_CONNECTIVITY_ALGO() |
||||
|
{ |
||||
|
Clear(); |
||||
|
} |
||||
|
|
||||
|
bool CN_CONNECTIVITY_ALGO::Remove( BOARD_ITEM* aItem ) |
||||
|
{ |
||||
|
markItemNetAsDirty ( aItem ); |
||||
|
|
||||
|
switch( aItem->Type() ) |
||||
|
{ |
||||
|
case PCB_MODULE_T: |
||||
|
for ( auto pad : static_cast<MODULE *> (aItem ) -> PadsIter() ) |
||||
|
{ |
||||
|
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( pad ) ].MarkItemsAsInvalid(); |
||||
|
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( pad ) ); |
||||
|
} |
||||
|
m_padList.SetDirty(true); |
||||
|
|
||||
|
break; |
||||
|
case PCB_PAD_T: |
||||
|
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid(); |
||||
|
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ); |
||||
|
m_padList.SetDirty(true); |
||||
|
break; |
||||
|
|
||||
|
case PCB_TRACE_T: |
||||
|
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid(); |
||||
|
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ); |
||||
|
m_trackList.SetDirty(true); |
||||
|
break; |
||||
|
|
||||
|
case PCB_VIA_T: |
||||
|
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid(); |
||||
|
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ); |
||||
|
m_viaList.SetDirty(true); |
||||
|
|
||||
|
break; |
||||
|
|
||||
|
|
||||
|
case PCB_ZONE_AREA_T: |
||||
|
case PCB_ZONE_T: |
||||
|
{ |
||||
|
m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid(); |
||||
|
m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ); |
||||
|
m_zoneList.SetDirty(true); |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::markItemNetAsDirty( const BOARD_ITEM *aItem ) |
||||
|
{ |
||||
|
if ( aItem->IsConnected () ) |
||||
|
{ |
||||
|
auto citem = static_cast<const BOARD_CONNECTED_ITEM*> ( aItem ); |
||||
|
markNetAsDirty ( citem->GetNetCode() ); |
||||
|
} else { |
||||
|
if ( aItem->Type() == PCB_MODULE_T ) |
||||
|
{ |
||||
|
auto mod = static_cast <const MODULE *> ( aItem ); |
||||
|
for( D_PAD* pad = mod->Pads(); pad; pad = pad->Next() ) |
||||
|
markNetAsDirty ( pad->GetNetCode() ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CN_CONNECTIVITY_ALGO::Add( BOARD_ITEM* aItem ) |
||||
|
{ |
||||
|
markItemNetAsDirty ( aItem ); |
||||
|
|
||||
|
switch( aItem->Type() ) |
||||
|
{ |
||||
|
case PCB_MODULE_T: |
||||
|
for ( auto pad : static_cast<MODULE *> (aItem ) -> PadsIter() ) |
||||
|
{ |
||||
|
if ( m_itemMap.find ( pad ) != m_itemMap.end() ) |
||||
|
return false; |
||||
|
|
||||
|
add( m_padList, pad ); |
||||
|
} |
||||
|
|
||||
|
break; |
||||
|
|
||||
|
case PCB_PAD_T: |
||||
|
if ( m_itemMap.find ( static_cast<D_PAD *> ( aItem ) ) != m_itemMap.end() ) |
||||
|
return false; |
||||
|
|
||||
|
add( m_padList, static_cast<D_PAD *> ( aItem ) ); |
||||
|
|
||||
|
break; |
||||
|
|
||||
|
case PCB_TRACE_T: |
||||
|
{ |
||||
|
if ( m_itemMap.find ( static_cast<TRACK *> ( aItem ) ) != m_itemMap.end() ) |
||||
|
return false; |
||||
|
|
||||
|
add( m_trackList, static_cast<TRACK *> ( aItem ) ); |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
case PCB_VIA_T: |
||||
|
if ( m_itemMap.find ( static_cast<VIA *> ( aItem ) ) != m_itemMap.end() ) |
||||
|
return false; |
||||
|
|
||||
|
add( m_viaList, static_cast<VIA*> (aItem )); |
||||
|
|
||||
|
break; |
||||
|
|
||||
|
|
||||
|
case PCB_ZONE_AREA_T: |
||||
|
case PCB_ZONE_T: |
||||
|
{ |
||||
|
auto zone = static_cast<ZONE_CONTAINER*> ( aItem ); |
||||
|
|
||||
|
if ( m_itemMap.find ( static_cast<ZONE_CONTAINER *> ( aItem ) ) != m_itemMap.end() ) |
||||
|
return false; |
||||
|
|
||||
|
m_itemMap[zone] = ITEM_MAP_ENTRY(); |
||||
|
|
||||
|
for( auto zitem : m_zoneList.Add( zone ) ) |
||||
|
m_itemMap[zone].Link(zitem); |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::searchConnections( bool aIncludeZones ) |
||||
|
{ |
||||
|
int totalDirtyCount = 0; |
||||
|
|
||||
|
if ( m_lastSearchWithZones != aIncludeZones ) |
||||
|
{ |
||||
|
m_padList.MarkAllAsDirty(); |
||||
|
m_viaList.MarkAllAsDirty(); |
||||
|
m_trackList.MarkAllAsDirty(); |
||||
|
m_zoneList.MarkAllAsDirty(); |
||||
|
} |
||||
|
|
||||
|
m_lastSearchWithZones = aIncludeZones; |
||||
|
|
||||
|
auto checkForConnection = [] ( const CN_ANCHOR_PTR point, CN_ITEM *aRefItem, int aMaxDist = 0) |
||||
|
{ |
||||
|
const auto parent = aRefItem->Parent(); |
||||
|
|
||||
|
|
||||
|
assert ( point->Item() ); |
||||
|
assert ( point->Item()->Parent() ); |
||||
|
assert ( aRefItem->Parent() ); |
||||
|
|
||||
|
if ( !point->Item()->Valid() ) |
||||
|
return; |
||||
|
|
||||
|
if ( !aRefItem->Valid() ) |
||||
|
return; |
||||
|
|
||||
|
if( parent == point->Item()->Parent() ) |
||||
|
return; |
||||
|
|
||||
|
if( !( parent->GetLayerSet() & |
||||
|
point->Item()->Parent()->GetLayerSet() ).any() ) |
||||
|
return; |
||||
|
|
||||
|
switch ( parent->Type() ) |
||||
|
{ |
||||
|
case PCB_PAD_T: |
||||
|
case PCB_VIA_T: |
||||
|
|
||||
|
if( parent->HitTest( wxPoint( point->Pos().x, point->Pos().y ) ) ) |
||||
|
CN_ITEM::Connect( aRefItem, point->Item() ); |
||||
|
|
||||
|
break; |
||||
|
case PCB_TRACE_T: |
||||
|
{ |
||||
|
const auto track = static_cast<TRACK*> ( parent ); |
||||
|
|
||||
|
const VECTOR2I d_start( VECTOR2I( track->GetStart() ) - point->Pos() ); |
||||
|
const VECTOR2I d_end( VECTOR2I( track->GetEnd() ) - point->Pos() ); |
||||
|
|
||||
|
if( d_start.EuclideanNorm() < aMaxDist |
||||
|
|| d_end.EuclideanNorm() < aMaxDist ) |
||||
|
CN_ITEM::Connect( aRefItem, point->Item() ); |
||||
|
break; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
case PCB_ZONE_T: |
||||
|
case PCB_ZONE_AREA_T: |
||||
|
{ |
||||
|
const auto zone = static_cast<ZONE_CONTAINER*> ( parent ); |
||||
|
auto zoneItem = static_cast<CN_ZONE*> ( aRefItem ); |
||||
|
|
||||
|
if( point->Item()->Net() != parent->GetNetCode() ) |
||||
|
return; |
||||
|
|
||||
|
if( !( zone->GetLayerSet() & |
||||
|
point->Item()->Parent()->GetLayerSet() ).any() ) |
||||
|
return; |
||||
|
|
||||
|
if ( zoneItem->ContainsAnchor ( point ) ) |
||||
|
{ |
||||
|
CN_ITEM::Connect( zoneItem, point->Item() ); |
||||
|
} |
||||
|
|
||||
|
break; |
||||
|
|
||||
|
} |
||||
|
default : |
||||
|
assert ( false ); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
auto checkInterZoneConnection = [] ( CN_ZONE* testedZone, CN_ZONE *aRefZone ) |
||||
|
{ |
||||
|
const auto parentZone = static_cast<const ZONE_CONTAINER*>(aRefZone->Parent()); |
||||
|
|
||||
|
if( testedZone->Parent()->Type () != PCB_ZONE_AREA_T ) |
||||
|
return; |
||||
|
|
||||
|
if (testedZone == aRefZone) |
||||
|
return; |
||||
|
|
||||
|
if (testedZone->Parent() == aRefZone->Parent()) |
||||
|
return; |
||||
|
|
||||
|
|
||||
|
if( testedZone->Net() != parentZone->GetNetCode() ) |
||||
|
return; // we only test zones belonging to the same net
|
||||
|
|
||||
|
if( !( testedZone->Parent()->GetLayerSet() & |
||||
|
parentZone->GetLayerSet() ).any() ) |
||||
|
return; // and on same layer
|
||||
|
|
||||
|
const auto& outline = parentZone->GetFilledPolysList().COutline( aRefZone->SubpolyIndex() ); |
||||
|
|
||||
|
for( int i = 0; i < outline.PointCount(); i++ ) |
||||
|
if( testedZone ->ContainsPoint( outline.CPoint(i) ) ) |
||||
|
{ |
||||
|
CN_ITEM::Connect ( aRefZone, testedZone ); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
const auto testedZoneParent = static_cast<const ZONE_CONTAINER*>(testedZone->Parent()); |
||||
|
|
||||
|
const auto& outline2 = testedZoneParent->GetFilledPolysList().COutline( testedZone->SubpolyIndex() ); |
||||
|
|
||||
|
for( int i = 0; i < outline2.PointCount(); i++ ) |
||||
|
if( aRefZone ->ContainsPoint( outline2.CPoint(i) ) ) |
||||
|
{ |
||||
|
CN_ITEM::Connect ( aRefZone, testedZone ); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
#ifdef CONNECTIVITY_DEBUG
|
||||
|
printf("Search start\n"); |
||||
|
#endif
|
||||
|
|
||||
|
std::vector<CN_ITEM *> garbage; |
||||
|
garbage.reserve(1024); |
||||
|
|
||||
|
m_padList.RemoveInvalidItems(garbage); |
||||
|
m_viaList.RemoveInvalidItems(garbage); |
||||
|
m_trackList.RemoveInvalidItems(garbage); |
||||
|
m_zoneList.RemoveInvalidItems(garbage); |
||||
|
|
||||
|
for ( auto item : garbage ) |
||||
|
delete item; |
||||
|
|
||||
|
//auto all = allItemsInBoard();
|
||||
|
|
||||
|
#ifdef CONNECTIVITY_DEBUG
|
||||
|
for ( auto item : m_padList ) |
||||
|
if ( all.find( item->Parent() ) == all.end() ) { printf("FAiling pad : %p\n", item->Parent() ); assert ( false ); } |
||||
|
for ( auto item : m_viaList ) |
||||
|
if ( all.find( item->Parent() ) == all.end() ) { printf("FAiling via : %p\n", item->Parent() ); assert ( false ); } |
||||
|
for ( auto item : m_trackList ) |
||||
|
if ( all.find( item->Parent() ) == all.end() ) { printf("FAiling track : %p\n", item->Parent() ); assert ( false ); } |
||||
|
for ( auto item : m_zoneList ) |
||||
|
if ( all.find( item->Parent() ) == all.end() ) { printf("FAiling zome : %p\n", item->Parent() ); assert ( false ); } |
||||
|
#endif
|
||||
|
|
||||
|
|
||||
|
using namespace std::placeholders; |
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
PROF_COUNTER search_cnt( "search-connections" ); |
||||
|
PROF_COUNTER search_basic( "search-basic" ); |
||||
|
#endif
|
||||
|
|
||||
|
if ( m_padList.IsDirty() || m_trackList.IsDirty() || m_viaList.IsDirty() ) |
||||
|
{ |
||||
|
totalDirtyCount++; |
||||
|
|
||||
|
for( auto padItem : m_padList ) |
||||
|
{ |
||||
|
auto pad = static_cast<D_PAD*> ( padItem->Parent() ); |
||||
|
auto searchPads = std::bind( checkForConnection, _1, padItem ); |
||||
|
|
||||
|
m_padList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); |
||||
|
m_trackList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); |
||||
|
m_viaList.FindNearby( pad->ShapePos(), pad->GetBoundingRadius(), searchPads ); |
||||
|
} |
||||
|
|
||||
|
for( auto& trackItem : m_trackList ) |
||||
|
{ |
||||
|
auto track = static_cast<TRACK*> ( trackItem->Parent() ); |
||||
|
int dist_max = track->GetWidth() / 2; |
||||
|
auto searchTracks = std::bind( checkForConnection, _1, trackItem, dist_max ); |
||||
|
|
||||
|
m_trackList.FindNearby( track->GetStart(), dist_max, searchTracks ); |
||||
|
m_trackList.FindNearby( track->GetEnd(), dist_max, searchTracks ); |
||||
|
} |
||||
|
|
||||
|
for( auto& viaItem : m_viaList ) |
||||
|
{ |
||||
|
auto via = static_cast<VIA*> ( viaItem->Parent() ); |
||||
|
int dist_max = via->GetWidth() / 2; |
||||
|
auto searchVias = std::bind( checkForConnection, _1, viaItem, dist_max ); |
||||
|
|
||||
|
totalDirtyCount++; |
||||
|
m_viaList.FindNearby( via->GetStart(), dist_max, searchVias ); |
||||
|
m_trackList.FindNearby( via->GetStart(), dist_max, searchVias ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
search_basic.Show(); |
||||
|
#endif
|
||||
|
|
||||
|
if( aIncludeZones ) |
||||
|
{ |
||||
|
for( auto& item : m_zoneList ) |
||||
|
{ |
||||
|
auto zoneItem = static_cast<CN_ZONE *> (item); |
||||
|
auto searchZones = std::bind( checkForConnection, _1, zoneItem ); |
||||
|
|
||||
|
if( zoneItem->Dirty() ) |
||||
|
{ |
||||
|
totalDirtyCount++; |
||||
|
m_viaList.FindNearby( zoneItem->BBox(), searchZones ); |
||||
|
m_trackList.FindNearby( zoneItem->BBox(), searchZones ); |
||||
|
m_padList.FindNearby( zoneItem->BBox(), searchZones ); |
||||
|
m_zoneList.FindNearbyZones( zoneItem->BBox(), std::bind( checkInterZoneConnection, _1, zoneItem ) ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
m_zoneList.ClearDirtyFlags(); |
||||
|
} |
||||
|
|
||||
|
m_padList.ClearDirtyFlags(); |
||||
|
m_viaList.ClearDirtyFlags(); |
||||
|
m_trackList.ClearDirtyFlags(); |
||||
|
|
||||
|
#ifdef CONNECTIVITY_DEBUG
|
||||
|
printf("Search end\n"); |
||||
|
#endif
|
||||
|
|
||||
|
#ifdef PROFILE
|
||||
|
search_cnt.Show(); |
||||
|
#endif
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
void CN_ITEM::RemoveInvalidRefs() |
||||
|
{ |
||||
|
auto lastConn = std::remove_if(m_connected.begin(), m_connected.end(), [] ( CN_ITEM * item) { |
||||
|
return !item->Valid(); |
||||
|
|
||||
|
} ); |
||||
|
|
||||
|
m_connected.resize( lastConn - m_connected.begin() ); |
||||
|
} |
||||
|
|
||||
|
void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM *>& aGarbage ) |
||||
|
{ |
||||
|
auto lastAnchor = std::remove_if(m_anchors.begin(), m_anchors.end(), [] ( const CN_ANCHOR_PTR anchor) { |
||||
|
return !anchor->Valid(); |
||||
|
|
||||
|
} ); |
||||
|
|
||||
|
m_anchors.resize( lastAnchor - m_anchors.begin() ); |
||||
|
|
||||
|
auto lastItem = std::remove_if(m_items.begin(), m_items.end(), [&aGarbage] ( CN_ITEM * item) { |
||||
|
if ( !item->Valid() ) |
||||
|
{ |
||||
|
aGarbage.push_back ( item ); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} ); |
||||
|
|
||||
|
m_items.resize( lastItem - m_items.begin() ); |
||||
|
|
||||
|
// fixme: mem leaks
|
||||
|
|
||||
|
for ( auto item : m_items ) |
||||
|
item->RemoveInvalidRefs(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CN_CONNECTIVITY_ALGO::isDirty() const |
||||
|
{ |
||||
|
return m_viaList.IsDirty() || m_trackList.IsDirty() || m_zoneList.IsDirty() || m_padList.IsDirty(); |
||||
|
} |
||||
|
|
||||
|
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode ) |
||||
|
{ |
||||
|
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_MODULE_T, EOT }; |
||||
|
return SearchClusters ( aMode, types, -1 ); |
||||
|
} |
||||
|
|
||||
|
const CN_CONNECTIVITY_ALGO::CLUSTERS CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet ) |
||||
|
{ |
||||
|
bool includeZones = ( aMode != CSM_PROPAGATE ); |
||||
|
bool withinAnyNet = ( aMode != CSM_PROPAGATE ); |
||||
|
|
||||
|
std::deque<CN_ITEM*> Q; |
||||
|
CN_ITEM* head = nullptr; |
||||
|
CLUSTERS clusters; |
||||
|
|
||||
|
if ( isDirty() ) |
||||
|
searchConnections( includeZones ); |
||||
|
|
||||
|
auto addToSearchList = [&head, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem ) |
||||
|
{ |
||||
|
if ( withinAnyNet && aItem->Net() <= 0 ) |
||||
|
return; |
||||
|
|
||||
|
if( !aItem->Valid() ) |
||||
|
return; |
||||
|
|
||||
|
if ( aSingleNet >=0 && aItem->Net() != aSingleNet ) |
||||
|
return; |
||||
|
|
||||
|
bool found = false; |
||||
|
|
||||
|
for ( int i = 0; aTypes[i] != EOT; i++ ) |
||||
|
if ( aItem->Parent()->Type() == aTypes[i] ) |
||||
|
{ |
||||
|
found = true; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (!found) |
||||
|
return; |
||||
|
|
||||
|
aItem->ListClear(); |
||||
|
aItem->SetVisited( false ); |
||||
|
|
||||
|
if ( !head ) |
||||
|
head = aItem; |
||||
|
else |
||||
|
head->ListInsert( aItem ); |
||||
|
}; |
||||
|
|
||||
|
std::for_each( m_padList.begin(), m_padList.end(), addToSearchList ); |
||||
|
std::for_each( m_trackList.begin(), m_trackList.end(), addToSearchList ); |
||||
|
std::for_each( m_viaList.begin(), m_viaList.end(), addToSearchList ); |
||||
|
|
||||
|
if (includeZones) |
||||
|
{ |
||||
|
std::for_each( m_zoneList.begin(), m_zoneList.end(), addToSearchList ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
while( head ) |
||||
|
{ |
||||
|
CN_CLUSTER_PTR cluster ( new CN_CLUSTER() ); |
||||
|
|
||||
|
Q.clear(); |
||||
|
CN_ITEM* root = head; |
||||
|
root->SetVisited ( true ); |
||||
|
|
||||
|
head = root->ListRemove(); |
||||
|
|
||||
|
Q.push_back( root ); |
||||
|
|
||||
|
while( Q.size() ) |
||||
|
{ |
||||
|
CN_ITEM* current = Q.front(); |
||||
|
|
||||
|
Q.pop_front(); |
||||
|
cluster->Add( current ); |
||||
|
|
||||
|
for( auto n : current->ConnectedItems() ) |
||||
|
{ |
||||
|
if ( withinAnyNet && n->Net() != root->Net() ) |
||||
|
continue; |
||||
|
|
||||
|
if( !n->Visited() && n->Valid() ) |
||||
|
{ |
||||
|
n->SetVisited( true ); |
||||
|
Q.push_back( n ); |
||||
|
head = n->ListRemove(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
clusters.push_back( cluster ); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
std::sort( clusters.begin(), clusters.end(), []( CN_CLUSTER_PTR a, CN_CLUSTER_PTR b ) { |
||||
|
return a->OriginNet() < b->OriginNet(); |
||||
|
} ); |
||||
|
|
||||
|
#ifdef CONNECTIVITY_DEBUG
|
||||
|
printf("Active clusters: %d\n"); |
||||
|
for (auto cl:clusters) |
||||
|
{ |
||||
|
printf("Net %d\n", cl->OriginNet()); |
||||
|
cl->Dump(); |
||||
|
} |
||||
|
#endif
|
||||
|
|
||||
|
return clusters; |
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard ) |
||||
|
{ |
||||
|
for( int i = 0; i<aBoard->GetAreaCount(); i++ ) |
||||
|
{ |
||||
|
auto zone = aBoard->GetArea( i ); |
||||
|
Add( zone ); |
||||
|
} |
||||
|
|
||||
|
for( auto tv : aBoard->Tracks() ) |
||||
|
Add( tv ); |
||||
|
|
||||
|
for( auto mod : aBoard->Modules() ) |
||||
|
for( auto pad : mod->PadsIter() ) |
||||
|
Add( pad ); |
||||
|
|
||||
|
/*wxLogTrace( "CN", "zones : %lu, pads : %lu vias : %lu tracks : %lu\n",
|
||||
|
m_zoneList.Size(), m_padList.Size(), |
||||
|
m_viaList.Size(), m_trackList.Size() );*/ |
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM *> &aItems ) |
||||
|
{ |
||||
|
for ( auto item : aItems ) |
||||
|
{ |
||||
|
switch( item->Type() ) |
||||
|
{ |
||||
|
case PCB_TRACE_T: |
||||
|
case PCB_VIA_T: |
||||
|
case PCB_ZONE_T: |
||||
|
case PCB_PAD_T: |
||||
|
Add( item ); |
||||
|
break; |
||||
|
|
||||
|
case PCB_MODULE_T: |
||||
|
{ |
||||
|
for( auto pad : static_cast<MODULE*>(item)->PadsIter() ) |
||||
|
{ |
||||
|
Add( pad ); |
||||
|
} |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::propagateConnections() |
||||
|
{ |
||||
|
for( auto cluster : m_connClusters ) |
||||
|
{ |
||||
|
if( cluster->IsConflicting() ) |
||||
|
{ |
||||
|
wxLogTrace( "CN", "Conflicting nets in cluster %p\n", cluster.get() ); |
||||
|
} |
||||
|
else if( cluster->IsOrphaned() ) |
||||
|
{ |
||||
|
wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]\n", cluster.get(), |
||||
|
(const char*) cluster->OriginNetName() ); |
||||
|
} |
||||
|
else if( cluster->HasValidNet() ) |
||||
|
{ |
||||
|
// normal cluster: just propagate from the pads
|
||||
|
int n_changed = 0; |
||||
|
|
||||
|
for( auto item : *cluster ) |
||||
|
{ |
||||
|
if( item->CanChangeNet() ) |
||||
|
{ |
||||
|
item->Parent()->SetNetCode( cluster->OriginNet() ); |
||||
|
n_changed++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if( n_changed ) |
||||
|
wxLogTrace( "CN", "Cluster %p : net : %d %s\n", cluster.get(), |
||||
|
cluster->OriginNet(), (const char*) cluster->OriginNetName() ); |
||||
|
else |
||||
|
wxLogTrace( "CN", "Cluster %p : nothing to propagate\n", cluster.get() ); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
wxLogTrace( "CN", "Cluster %p : connected to unused net\n", cluster.get() ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::PropagateNets() |
||||
|
{ |
||||
|
//searchConnections( false );
|
||||
|
m_connClusters = SearchClusters( CSM_PROPAGATE ); |
||||
|
propagateConnections(); |
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands ) |
||||
|
{ |
||||
|
|
||||
|
if ( aZone->GetFilledPolysList().IsEmpty() ) |
||||
|
return; |
||||
|
|
||||
|
aIslands.clear(); |
||||
|
|
||||
|
Remove( aZone ); |
||||
|
Add( aZone ); |
||||
|
|
||||
|
m_connClusters = SearchClusters( CSM_CONNECTIVITY_CHECK ); |
||||
|
|
||||
|
for( auto cluster : m_connClusters ) |
||||
|
if( cluster->Contains( aZone ) && cluster->IsOrphaned() ) |
||||
|
{ |
||||
|
for( auto z : *cluster ) |
||||
|
{ |
||||
|
if( z->Parent() == aZone ) |
||||
|
{ |
||||
|
aIslands.push_back( static_cast<CN_ZONE*>(z)->SubpolyIndex() ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
wxLogTrace( "CN", "Found %llu isolated islands\n", aIslands.size() ); |
||||
|
} |
||||
|
|
||||
|
const CN_CONNECTIVITY_ALGO::CLUSTERS& CN_CONNECTIVITY_ALGO::GetClusters() |
||||
|
{ |
||||
|
m_ratsnestClusters = SearchClusters( CSM_RATSNEST ); |
||||
|
return m_ratsnestClusters; |
||||
|
}; |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::markNetAsDirty ( int aNet ) |
||||
|
{ |
||||
|
if(aNet <= 0) |
||||
|
return; |
||||
|
|
||||
|
if(m_dirtyNets.size() <= aNet ) |
||||
|
m_dirtyNets.resize(aNet + 1); |
||||
|
m_dirtyNets[ aNet ] = true; |
||||
|
} |
||||
|
|
||||
|
int CN_ITEM::AnchorCount() const |
||||
|
{ |
||||
|
return m_parent->Type() == PCB_TRACE_T ? 2 : 1; |
||||
|
} |
||||
|
|
||||
|
const VECTOR2I CN_ITEM::GetAnchor( int n ) const |
||||
|
{ |
||||
|
switch ( m_parent->Type() ) |
||||
|
{ |
||||
|
case PCB_PAD_T: |
||||
|
return static_cast<const D_PAD *>(m_parent)->ShapePos(); |
||||
|
break; |
||||
|
|
||||
|
case PCB_TRACE_T: |
||||
|
{ |
||||
|
auto tr = static_cast<const TRACK *>(m_parent); |
||||
|
return (n == 0 ? tr->GetStart() : tr->GetEnd() ); |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case PCB_VIA_T: |
||||
|
return static_cast<const VIA *>(m_parent)->GetStart(); |
||||
|
|
||||
|
default: |
||||
|
assert(false); |
||||
|
return VECTOR2I(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int CN_ZONE::AnchorCount() const |
||||
|
{ |
||||
|
const auto zone = static_cast<const ZONE_CONTAINER*> ( Parent() ); |
||||
|
const auto& outline = zone->GetFilledPolysList().COutline( m_subpolyIndex ); |
||||
|
|
||||
|
return outline.PointCount() ? 1 : 0; |
||||
|
} |
||||
|
|
||||
|
const VECTOR2I CN_ZONE::GetAnchor(int n ) const |
||||
|
{ |
||||
|
const auto zone = static_cast<const ZONE_CONTAINER*> ( Parent() ); |
||||
|
const auto& outline = zone->GetFilledPolysList().COutline( m_subpolyIndex ); |
||||
|
|
||||
|
return outline.CPoint(0); |
||||
|
} |
||||
|
|
||||
|
/*const std::vector<VECTOR2I> CN_CLUSTER::GetAnchors()
|
||||
|
{ |
||||
|
std::vector<VECTOR2I> anchors; |
||||
|
|
||||
|
for ( auto item : m_items ) |
||||
|
{ |
||||
|
int cnt = item->AnchorCount(); |
||||
|
for (int i = 0 ; i < cnt; i++) |
||||
|
{ |
||||
|
anchors.push_back( item->GetAnchor(i) ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return anchors; |
||||
|
}*/ |
||||
|
|
||||
|
int CN_ITEM::Net() const |
||||
|
{ |
||||
|
if (!m_parent) |
||||
|
return -1; |
||||
|
return m_parent->GetNetCode(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
BOARD_CONNECTED_ITEM *CN_ANCHOR::Parent() const |
||||
|
{ |
||||
|
return m_item->Parent(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
bool CN_ANCHOR::Valid() const |
||||
|
{ |
||||
|
if( !m_item ) |
||||
|
return false; |
||||
|
return m_item->Valid(); |
||||
|
} |
||||
|
|
||||
|
void CN_CONNECTIVITY_ALGO::Clear() |
||||
|
{ |
||||
|
m_ratsnestClusters.clear(); |
||||
|
m_connClusters.clear(); |
||||
|
m_itemMap.clear(); |
||||
|
m_padList.Clear(); |
||||
|
m_trackList.Clear(); |
||||
|
m_viaList.Clear(); |
||||
|
m_zoneList.Clear(); |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,926 @@ |
|||||
|
/* |
||||
|
* This program source code file is part of KICAD, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2013-2017 CERN |
||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch> |
||||
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> |
||||
|
* |
||||
|
* 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 |
||||
|
*/ |
||||
|
|
||||
|
// #define CONNECTIVITY_DEBUG |
||||
|
|
||||
|
#ifndef __CONNECTIVITY_ALGO_H |
||||
|
#define __CONNECTIVITY_ALGO_H |
||||
|
|
||||
|
#include <class_board.h> |
||||
|
#include <class_pad.h> |
||||
|
#include <class_module.h> |
||||
|
#include <class_zone.h> |
||||
|
|
||||
|
#include <geometry/shape_poly_set.h> |
||||
|
#include <geometry/poly_grid_partition.h> |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <algorithm> |
||||
|
#include <functional> |
||||
|
#include <vector> |
||||
|
#include <deque> |
||||
|
|
||||
|
#include <connectivity.h> |
||||
|
|
||||
|
class CN_ITEM; |
||||
|
class CN_CONNECTIVITY_ALGO_IMPL; |
||||
|
class CN_RATSNEST_NODES; |
||||
|
class CN_CLUSTER; |
||||
|
class BOARD; |
||||
|
class BOARD_CONNECTED_ITEM; |
||||
|
class BOARD_ITEM; |
||||
|
class ZONE_CONTAINER; |
||||
|
|
||||
|
class CN_ANCHOR |
||||
|
{ |
||||
|
public: |
||||
|
CN_ANCHOR() |
||||
|
{ |
||||
|
m_item = nullptr; |
||||
|
} |
||||
|
|
||||
|
CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem ) |
||||
|
{ |
||||
|
m_pos = aPos; |
||||
|
m_item = aItem; |
||||
|
assert( m_item ); |
||||
|
} |
||||
|
|
||||
|
bool Valid() const; |
||||
|
|
||||
|
|
||||
|
CN_ITEM* Item() const |
||||
|
{ |
||||
|
return m_item; |
||||
|
} |
||||
|
|
||||
|
BOARD_CONNECTED_ITEM* Parent() const; |
||||
|
|
||||
|
const VECTOR2I& Pos() const |
||||
|
{ |
||||
|
return m_pos; |
||||
|
} |
||||
|
|
||||
|
bool IsDirty() const; |
||||
|
|
||||
|
/// Returns tag, common identifier for connected nodes |
||||
|
inline int GetTag() const |
||||
|
{ |
||||
|
return m_tag; |
||||
|
} |
||||
|
|
||||
|
/// Sets tag, common identifier for connected nodes |
||||
|
inline void SetTag( int aTag ) |
||||
|
{ |
||||
|
m_tag = aTag; |
||||
|
} |
||||
|
|
||||
|
/// Decides whether this node can be a ratsnest line target |
||||
|
inline void SetNoLine( bool aEnable ) |
||||
|
{ |
||||
|
m_noline = aEnable; |
||||
|
} |
||||
|
|
||||
|
/// Returns true if this node can be a target for ratsnest lines |
||||
|
inline const bool& GetNoLine() const |
||||
|
{ |
||||
|
return m_noline; |
||||
|
} |
||||
|
|
||||
|
inline void SetCluster( std::shared_ptr<CN_CLUSTER> aCluster ) |
||||
|
{ |
||||
|
m_cluster = aCluster; |
||||
|
} |
||||
|
|
||||
|
inline std::shared_ptr<CN_CLUSTER> GetCluster() const |
||||
|
{ |
||||
|
return m_cluster; |
||||
|
} |
||||
|
|
||||
|
// Tag used for unconnected items. |
||||
|
static const int TAG_UNCONNECTED = -1; |
||||
|
|
||||
|
private: |
||||
|
/// Position of the anchor |
||||
|
VECTOR2I m_pos; |
||||
|
|
||||
|
/// Item owning the anchor |
||||
|
CN_ITEM* m_item = nullptr; |
||||
|
|
||||
|
/// Tag for quick connection resolution |
||||
|
int m_tag = -1; |
||||
|
|
||||
|
/// Whether it the node can be a target for ratsnest lines |
||||
|
bool m_noline = false; |
||||
|
|
||||
|
/// Cluster to which the anchor belongs |
||||
|
std::shared_ptr<CN_CLUSTER> m_cluster; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
typedef std::shared_ptr<CN_ANCHOR> CN_ANCHOR_PTR; |
||||
|
typedef std::vector<CN_ANCHOR_PTR> CN_ANCHORS; |
||||
|
|
||||
|
class CN_EDGE |
||||
|
{ |
||||
|
public: |
||||
|
CN_EDGE() {}; |
||||
|
CN_EDGE( CN_ANCHOR_PTR aSource, CN_ANCHOR_PTR aTarget, int aWeight = 0 ) : |
||||
|
m_source( aSource ), |
||||
|
m_target( aTarget ), |
||||
|
m_weight( aWeight ) {} |
||||
|
|
||||
|
CN_ANCHOR_PTR GetSourceNode() const { return m_source; } |
||||
|
CN_ANCHOR_PTR GetTargetNode() const { return m_target; } |
||||
|
int GetWeight() const { return m_weight; } |
||||
|
|
||||
|
void SetSourceNode( const CN_ANCHOR_PTR& aNode ) { m_source = aNode; } |
||||
|
void SetTargetNode( const CN_ANCHOR_PTR& aNode ) { m_target = aNode; } |
||||
|
void SetWeight( unsigned int weight ) { m_weight = weight; } |
||||
|
|
||||
|
private: |
||||
|
CN_ANCHOR_PTR m_source; |
||||
|
CN_ANCHOR_PTR m_target; |
||||
|
unsigned int m_weight = 0; |
||||
|
}; |
||||
|
|
||||
|
class CN_CLUSTER |
||||
|
{ |
||||
|
private: |
||||
|
|
||||
|
bool m_conflicting = false; |
||||
|
int m_originNet = 0; |
||||
|
CN_ITEM* m_originPad = nullptr; |
||||
|
std::vector<CN_ITEM*> m_items; |
||||
|
|
||||
|
public: |
||||
|
CN_CLUSTER(); |
||||
|
~CN_CLUSTER(); |
||||
|
|
||||
|
bool HasValidNet() const |
||||
|
{ |
||||
|
return m_originNet >= 0; |
||||
|
} |
||||
|
|
||||
|
int OriginNet() const |
||||
|
{ |
||||
|
return m_originNet; |
||||
|
} |
||||
|
|
||||
|
wxString OriginNetName() const; |
||||
|
|
||||
|
bool Contains( const CN_ITEM* aItem ); |
||||
|
bool Contains( const BOARD_CONNECTED_ITEM* aItem ); |
||||
|
void Dump(); |
||||
|
|
||||
|
int Size() const |
||||
|
{ |
||||
|
return m_items.size(); |
||||
|
} |
||||
|
|
||||
|
bool HasNet() const |
||||
|
{ |
||||
|
return m_originNet >= 0; |
||||
|
} |
||||
|
|
||||
|
bool IsOrphaned() const |
||||
|
{ |
||||
|
return m_originPad == nullptr; |
||||
|
} |
||||
|
|
||||
|
bool IsConflicting() const |
||||
|
{ |
||||
|
return m_conflicting; |
||||
|
} |
||||
|
|
||||
|
void Add( CN_ITEM* item ); |
||||
|
|
||||
|
using ITER = decltype(m_items)::iterator; |
||||
|
|
||||
|
ITER begin() { return m_items.begin(); }; |
||||
|
ITER end() { return m_items.end(); }; |
||||
|
}; |
||||
|
|
||||
|
typedef std::shared_ptr<CN_CLUSTER> CN_CLUSTER_PTR; |
||||
|
|
||||
|
// a lightweight intrusive list container |
||||
|
template <class T> |
||||
|
class INTRUSIVE_LIST |
||||
|
{ |
||||
|
public: |
||||
|
INTRUSIVE_LIST<T>() |
||||
|
{ |
||||
|
ListClear(); |
||||
|
} |
||||
|
|
||||
|
void ListClear() |
||||
|
{ |
||||
|
m_prev = nullptr; |
||||
|
m_next = nullptr; |
||||
|
m_root = (T*) this; |
||||
|
m_count = 1; |
||||
|
} |
||||
|
|
||||
|
T* ListRemove() |
||||
|
{ |
||||
|
if( m_prev ) |
||||
|
m_prev->m_next = m_next; |
||||
|
|
||||
|
if( m_next ) |
||||
|
m_next->m_prev = m_prev; |
||||
|
|
||||
|
m_root->m_count--; |
||||
|
|
||||
|
T* rv = nullptr; |
||||
|
|
||||
|
if( m_prev ) |
||||
|
rv = m_prev; |
||||
|
else if( m_next ) |
||||
|
rv = m_next; |
||||
|
|
||||
|
m_root = nullptr; |
||||
|
m_prev = nullptr; |
||||
|
m_next = nullptr; |
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
int ListSize() const |
||||
|
{ |
||||
|
return m_root ? m_root->m_count : 0; |
||||
|
} |
||||
|
|
||||
|
void ListInsert( T* item ) |
||||
|
{ |
||||
|
if( !m_root ) |
||||
|
m_root = item; |
||||
|
|
||||
|
if( m_next ) |
||||
|
m_next->m_prev = item; |
||||
|
|
||||
|
item->m_prev = (T*) this; |
||||
|
item->m_next = m_next; |
||||
|
item->m_root = m_root; |
||||
|
m_root->m_count++; |
||||
|
|
||||
|
m_next = item; |
||||
|
} |
||||
|
|
||||
|
T* ListNext() const { return m_next; }; |
||||
|
T* ListPrev() const { return m_prev; }; |
||||
|
|
||||
|
private: |
||||
|
int m_count; |
||||
|
T* m_prev; |
||||
|
T* m_next; |
||||
|
T* m_root; |
||||
|
}; |
||||
|
|
||||
|
// basic connectivity item |
||||
|
class CN_ITEM : public INTRUSIVE_LIST<CN_ITEM> |
||||
|
{ |
||||
|
private: |
||||
|
BOARD_CONNECTED_ITEM* m_parent; |
||||
|
|
||||
|
using CONNECTED_ITEMS = std::vector<CN_ITEM*>; |
||||
|
|
||||
|
// list of items physically connected (touching) |
||||
|
CONNECTED_ITEMS m_connected; |
||||
|
|
||||
|
CN_ANCHORS m_anchors; |
||||
|
|
||||
|
// visited flag for the BFS scan |
||||
|
bool m_visited; |
||||
|
|
||||
|
// can the net propagator modify the netcode? |
||||
|
bool m_canChangeNet; |
||||
|
|
||||
|
// valid flag, used to identify garbage items (we use lazy removal) |
||||
|
bool m_valid; |
||||
|
|
||||
|
// dirty flag, used to identify recently added item not yet scanned into the connectivity search |
||||
|
bool m_dirty; |
||||
|
|
||||
|
public: |
||||
|
void Dump(); |
||||
|
|
||||
|
CN_ITEM( BOARD_CONNECTED_ITEM* aParent, bool aCanChangeNet, int aAnchorCount = 2 ) |
||||
|
{ |
||||
|
m_parent = aParent; |
||||
|
m_canChangeNet = aCanChangeNet; |
||||
|
m_visited = false; |
||||
|
m_valid = true; |
||||
|
m_dirty = true; |
||||
|
m_anchors.reserve( 2 ); |
||||
|
} |
||||
|
|
||||
|
virtual ~CN_ITEM() {}; |
||||
|
|
||||
|
CN_ANCHOR_PTR AddAnchor( const VECTOR2I& aPos ) |
||||
|
{ |
||||
|
m_anchors.emplace_back( std::make_shared<CN_ANCHOR> ( aPos, this ) ); |
||||
|
//printf("%p add %d\n", this, m_anchors.size() ); |
||||
|
return m_anchors.back(); |
||||
|
} |
||||
|
|
||||
|
CN_ANCHORS& Anchors() |
||||
|
{ |
||||
|
return m_anchors; |
||||
|
} |
||||
|
|
||||
|
void SetValid( bool aValid ) |
||||
|
{ |
||||
|
m_valid = aValid; |
||||
|
} |
||||
|
|
||||
|
bool Valid() const |
||||
|
{ |
||||
|
return m_valid; |
||||
|
} |
||||
|
|
||||
|
void SetDirty( bool aDirty ) |
||||
|
{ |
||||
|
m_dirty = aDirty; |
||||
|
} |
||||
|
|
||||
|
bool Dirty() const |
||||
|
{ |
||||
|
return m_dirty; |
||||
|
} |
||||
|
|
||||
|
BOARD_CONNECTED_ITEM* Parent() const |
||||
|
{ |
||||
|
return m_parent; |
||||
|
} |
||||
|
|
||||
|
const CONNECTED_ITEMS& ConnectedItems() const |
||||
|
{ |
||||
|
return m_connected; |
||||
|
} |
||||
|
|
||||
|
void ClearConnections() |
||||
|
{ |
||||
|
m_connected.clear(); |
||||
|
} |
||||
|
|
||||
|
void SetVisited( bool aVisited ) |
||||
|
{ |
||||
|
m_visited = aVisited; |
||||
|
} |
||||
|
|
||||
|
bool Visited() const |
||||
|
{ |
||||
|
return m_visited; |
||||
|
} |
||||
|
|
||||
|
bool CanChangeNet() const |
||||
|
{ |
||||
|
return m_canChangeNet; |
||||
|
} |
||||
|
|
||||
|
static void Connect( CN_ITEM* a, CN_ITEM* b ) |
||||
|
{ |
||||
|
bool foundA = false, foundB = false; |
||||
|
|
||||
|
for( auto item : a->m_connected ) |
||||
|
{ |
||||
|
if( item == b ) |
||||
|
{ |
||||
|
foundA = true; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for( auto item : b->m_connected ) |
||||
|
{ |
||||
|
if( item == a ) |
||||
|
{ |
||||
|
foundB = true; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if( !foundA ) |
||||
|
a->m_connected.push_back( b ); |
||||
|
|
||||
|
if( !foundB ) |
||||
|
b->m_connected.push_back( a ); |
||||
|
} |
||||
|
|
||||
|
void RemoveInvalidRefs(); |
||||
|
|
||||
|
virtual int AnchorCount() const; |
||||
|
virtual const VECTOR2I GetAnchor( int n ) const; |
||||
|
|
||||
|
int Net() const; |
||||
|
}; |
||||
|
|
||||
|
typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR; |
||||
|
|
||||
|
class CN_LIST |
||||
|
{ |
||||
|
private: |
||||
|
bool m_dirty; |
||||
|
std::vector<CN_ANCHOR_PTR> m_anchors; |
||||
|
|
||||
|
protected: |
||||
|
std::vector<CN_ITEM*> m_items; |
||||
|
|
||||
|
void addAnchor( VECTOR2I pos, CN_ITEM* item ) |
||||
|
{ |
||||
|
m_anchors.push_back( item->AddAnchor( pos ) ); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
void sort() |
||||
|
{ |
||||
|
if( m_dirty ) |
||||
|
{ |
||||
|
std::sort( m_anchors.begin(), m_anchors.end() ); |
||||
|
|
||||
|
m_dirty = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
CN_LIST() |
||||
|
{ |
||||
|
m_dirty = false; |
||||
|
}; |
||||
|
|
||||
|
void Clear() |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
delete item; |
||||
|
|
||||
|
m_items.clear(); |
||||
|
} |
||||
|
|
||||
|
using ITER = decltype(m_items)::iterator; |
||||
|
|
||||
|
ITER begin() { return m_items.begin(); }; |
||||
|
ITER end() { return m_items.end(); }; |
||||
|
|
||||
|
template <class T> |
||||
|
void FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly = false ); |
||||
|
|
||||
|
template <class T> |
||||
|
void FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly = false ); |
||||
|
|
||||
|
void SetDirty( bool aDirty = true ) |
||||
|
{ |
||||
|
m_dirty = aDirty; |
||||
|
} |
||||
|
|
||||
|
bool IsDirty() const |
||||
|
{ |
||||
|
return m_dirty; |
||||
|
} |
||||
|
|
||||
|
void ClearConnections() |
||||
|
{ |
||||
|
for( auto& anchor : m_anchors ) |
||||
|
anchor->Item()->ClearConnections(); |
||||
|
} |
||||
|
|
||||
|
void RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage ); |
||||
|
|
||||
|
void ClearDirtyFlags() |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
item->SetDirty( false ); |
||||
|
|
||||
|
SetDirty( false ); |
||||
|
} |
||||
|
|
||||
|
void MarkAllAsDirty() |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
item->SetDirty( true ); |
||||
|
|
||||
|
SetDirty( true ); |
||||
|
} |
||||
|
|
||||
|
int Size() const |
||||
|
{ |
||||
|
return m_items.size(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
class CN_PAD_LIST : public CN_LIST |
||||
|
{ |
||||
|
public: |
||||
|
|
||||
|
CN_ITEM* Add( D_PAD* pad ) |
||||
|
{ |
||||
|
auto item = new CN_ITEM( pad, false, 2 ); |
||||
|
|
||||
|
addAnchor( pad->ShapePos(), item ); |
||||
|
m_items.push_back( item ); |
||||
|
|
||||
|
SetDirty(); |
||||
|
return item; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
class CN_TRACK_LIST : public CN_LIST |
||||
|
{ |
||||
|
public: |
||||
|
CN_ITEM* Add( TRACK* track ) |
||||
|
{ |
||||
|
auto item = new CN_ITEM( track, true ); |
||||
|
|
||||
|
m_items.push_back( item ); |
||||
|
|
||||
|
addAnchor( track->GetStart(), item ); |
||||
|
addAnchor( track->GetEnd(), item ); |
||||
|
SetDirty(); |
||||
|
|
||||
|
return item; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
class CN_VIA_LIST : public CN_LIST |
||||
|
{ |
||||
|
public: |
||||
|
CN_ITEM* Add( VIA* via ) |
||||
|
{ |
||||
|
auto item = new CN_ITEM( via, true ); |
||||
|
|
||||
|
m_items.push_back( item ); |
||||
|
addAnchor( via->GetStart(), item ); |
||||
|
SetDirty(); |
||||
|
return item; |
||||
|
}; |
||||
|
}; |
||||
|
|
||||
|
class CN_ZONE : public CN_ITEM |
||||
|
{ |
||||
|
public: |
||||
|
CN_ZONE( ZONE_CONTAINER* aParent, bool aCanChangeNet, int aSubpolyIndex ) : |
||||
|
CN_ITEM( aParent, aCanChangeNet ), |
||||
|
m_subpolyIndex( aSubpolyIndex ) |
||||
|
{ |
||||
|
SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList().COutline( aSubpolyIndex ); |
||||
|
|
||||
|
outline.SetClosed( true ); |
||||
|
outline.Simplify(); |
||||
|
|
||||
|
m_cachedPoly.reset( new POLY_GRID_PARTITION( outline, 16 ) ); |
||||
|
} |
||||
|
|
||||
|
int SubpolyIndex() const |
||||
|
{ |
||||
|
return m_subpolyIndex; |
||||
|
} |
||||
|
|
||||
|
bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const |
||||
|
{ |
||||
|
return m_cachedPoly->ContainsPoint( anchor->Pos() ); |
||||
|
} |
||||
|
|
||||
|
bool ContainsPoint( const VECTOR2I p ) const |
||||
|
{ |
||||
|
return m_cachedPoly->ContainsPoint( p ); |
||||
|
} |
||||
|
|
||||
|
const BOX2I& BBox() const |
||||
|
{ |
||||
|
return m_cachedPoly->BBox(); |
||||
|
} |
||||
|
|
||||
|
virtual int AnchorCount() const; |
||||
|
virtual const VECTOR2I GetAnchor( int n ) const; |
||||
|
|
||||
|
private: |
||||
|
std::vector<VECTOR2I> m_testOutlinePoints; |
||||
|
std::unique_ptr<POLY_GRID_PARTITION> m_cachedPoly; |
||||
|
int m_subpolyIndex; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
class CN_ZONE_LIST : public CN_LIST |
||||
|
{ |
||||
|
public: |
||||
|
CN_ZONE_LIST() {} |
||||
|
|
||||
|
const std::vector<CN_ITEM*> Add( ZONE_CONTAINER* zone ) |
||||
|
{ |
||||
|
const auto& polys = zone->GetFilledPolysList(); |
||||
|
|
||||
|
std::vector<CN_ITEM*> rv; |
||||
|
|
||||
|
for( int j = 0; j < polys.OutlineCount(); j++ ) |
||||
|
{ |
||||
|
CN_ZONE* zitem = new CN_ZONE( zone, false, j ); |
||||
|
const auto& outline = zone->GetFilledPolysList().COutline( j ); |
||||
|
|
||||
|
for( int k = 0; k < outline.PointCount(); k++ ) |
||||
|
addAnchor( outline.CPoint( k ), zitem ); |
||||
|
|
||||
|
m_items.push_back( zitem ); |
||||
|
rv.push_back( zitem ); |
||||
|
SetDirty(); |
||||
|
} |
||||
|
|
||||
|
return rv; |
||||
|
}; |
||||
|
|
||||
|
template <class T> |
||||
|
void FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly = false ); |
||||
|
}; |
||||
|
|
||||
|
template <class T> |
||||
|
void CN_LIST::FindNearby( BOX2I aBBox, T aFunc, bool aDirtyOnly ) |
||||
|
{ |
||||
|
for( auto p : m_anchors ) |
||||
|
{ |
||||
|
if( p->Valid() && aBBox.Contains( p->Pos() ) ) |
||||
|
if( !aDirtyOnly || p->IsDirty() ) |
||||
|
aFunc( p ); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <class T> |
||||
|
void CN_ZONE_LIST::FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly ) |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
{ |
||||
|
auto zone = static_cast<CN_ZONE*> ( item ); |
||||
|
|
||||
|
if( aBBox.Intersects( zone->BBox() ) ) |
||||
|
{ |
||||
|
if( !aDirtyOnly || zone->Dirty() ) |
||||
|
{ |
||||
|
aFunc( zone ); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
template <class T> |
||||
|
void CN_LIST::FindNearby( VECTOR2I aPosition, int aDistMax, T aFunc, bool aDirtyOnly ) |
||||
|
{ |
||||
|
/* Search items in m_Candidates that position is <= aDistMax from aPosition |
||||
|
* (Rectilinear distance) |
||||
|
* m_Candidates is sorted by X then Y values, so a fast binary search is used |
||||
|
* to locate the "best" entry point in list |
||||
|
* The best entry is a pad having its m_Pos.x == (or near) aPosition.x |
||||
|
* All candidates are near this candidate in list |
||||
|
* So from this entry point, a linear search is made to find all candidates |
||||
|
*/ |
||||
|
|
||||
|
sort(); |
||||
|
|
||||
|
int idxmax = m_anchors.size() - 1; |
||||
|
|
||||
|
int delta = idxmax + 1; |
||||
|
int idx = 0; // Starting index is the beginning of list |
||||
|
|
||||
|
while( delta ) |
||||
|
{ |
||||
|
// Calculate half size of remaining interval to test. |
||||
|
// Ensure the computed value is not truncated (too small) |
||||
|
if( (delta & 1) && ( delta > 1 ) ) |
||||
|
delta++; |
||||
|
|
||||
|
delta /= 2; |
||||
|
|
||||
|
auto p = m_anchors[idx]; |
||||
|
|
||||
|
int dist = p->Pos().x - aPosition.x; |
||||
|
|
||||
|
if( std::abs( dist ) <= aDistMax ) |
||||
|
{ |
||||
|
break; // A good entry point is found. The list can be scanned from this point. |
||||
|
} |
||||
|
else if( p->Pos().x < aPosition.x ) // We should search after this point |
||||
|
{ |
||||
|
idx += delta; |
||||
|
|
||||
|
if( idx > idxmax ) |
||||
|
idx = idxmax; |
||||
|
} |
||||
|
else // We should search before this p |
||||
|
{ |
||||
|
idx -= delta; |
||||
|
|
||||
|
if( idx < 0 ) |
||||
|
idx = 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Now explore the candidate list from the "best" entry point found |
||||
|
* (candidate "near" aPosition.x) |
||||
|
* We exp the list until abs(candidate->m_Point.x - aPosition.x) > aDistMashar* Currently a linear search is made because the number of candidates |
||||
|
* having the right X position is usually small |
||||
|
*/ |
||||
|
// search next candidates in list |
||||
|
VECTOR2I diff; |
||||
|
|
||||
|
for( int ii = idx; ii <= idxmax; ii++ ) |
||||
|
{ |
||||
|
auto& p = m_anchors[ii]; |
||||
|
diff = p->Pos() - aPosition;; |
||||
|
|
||||
|
if( std::abs( diff.x ) > aDistMax ) |
||||
|
break; // Exit: the distance is to long, we cannot find other candidates |
||||
|
|
||||
|
if( std::abs( diff.y ) > aDistMax ) |
||||
|
continue; // the y distance is to long, but we can find other candidates |
||||
|
|
||||
|
// We have here a good candidate: add it |
||||
|
if( p->Valid() ) |
||||
|
if( !aDirtyOnly || p->IsDirty() ) |
||||
|
aFunc( p ); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
// search previous candidates in list |
||||
|
for( int ii = idx - 1; ii >=0; ii-- ) |
||||
|
{ |
||||
|
auto& p = m_anchors[ii]; |
||||
|
diff = p->Pos() - aPosition; |
||||
|
|
||||
|
if( abs( diff.x ) > aDistMax ) |
||||
|
break; |
||||
|
|
||||
|
if( abs( diff.y ) > aDistMax ) |
||||
|
continue; |
||||
|
|
||||
|
// We have here a good candidate:add it |
||||
|
if( p->Valid() ) |
||||
|
if( !aDirtyOnly || p->IsDirty() ) |
||||
|
aFunc( p ); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
class CN_CONNECTIVITY_ALGO |
||||
|
{ |
||||
|
public: |
||||
|
enum CLUSTER_SEARCH_MODE |
||||
|
{ |
||||
|
CSM_PROPAGATE, |
||||
|
CSM_CONNECTIVITY_CHECK, |
||||
|
CSM_RATSNEST |
||||
|
}; |
||||
|
|
||||
|
using CLUSTERS = std::vector<CN_CLUSTER_PTR>; |
||||
|
|
||||
|
private: |
||||
|
|
||||
|
bool m_lastSearchWithZones = false; |
||||
|
|
||||
|
class ITEM_MAP_ENTRY |
||||
|
{ |
||||
|
public: |
||||
|
ITEM_MAP_ENTRY( CN_ITEM* aItem = nullptr ) |
||||
|
{ |
||||
|
if( aItem ) |
||||
|
m_items.push_back( aItem ); |
||||
|
} |
||||
|
|
||||
|
void MarkItemsAsInvalid() |
||||
|
{ |
||||
|
for( auto item : m_items ) |
||||
|
{ |
||||
|
item->SetValid( false ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void Link( CN_ITEM* aItem ) |
||||
|
{ |
||||
|
m_items.push_back( aItem ); |
||||
|
} |
||||
|
|
||||
|
const std::list<CN_ITEM*> GetItems() const |
||||
|
{ |
||||
|
return m_items; |
||||
|
} |
||||
|
|
||||
|
std::list<CN_ITEM*> m_items; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
CN_PAD_LIST m_padList; |
||||
|
CN_TRACK_LIST m_trackList; |
||||
|
CN_VIA_LIST m_viaList; |
||||
|
CN_ZONE_LIST m_zoneList; |
||||
|
|
||||
|
using ITEM_MAP_PAIR = std::pair <const BOARD_CONNECTED_ITEM*, ITEM_MAP_ENTRY>; |
||||
|
|
||||
|
std::unordered_map<const BOARD_CONNECTED_ITEM*, ITEM_MAP_ENTRY> m_itemMap; |
||||
|
|
||||
|
CLUSTERS m_connClusters; |
||||
|
CLUSTERS m_ratsnestClusters; |
||||
|
std::vector<bool> m_dirtyNets; |
||||
|
|
||||
|
void searchConnections( bool aIncludeZones = false ); |
||||
|
|
||||
|
void update(); |
||||
|
void propagateConnections(); |
||||
|
|
||||
|
template <class Container, class BItem> |
||||
|
void add( Container& c, BItem brditem ) |
||||
|
{ |
||||
|
auto item = c.Add( brditem ); |
||||
|
|
||||
|
m_itemMap[ brditem ] = ITEM_MAP_ENTRY( item ); |
||||
|
} |
||||
|
|
||||
|
bool addConnectedItem( BOARD_CONNECTED_ITEM* aItem ); |
||||
|
bool isDirty() const; |
||||
|
|
||||
|
void markNetAsDirty( int aNet ); |
||||
|
void markItemNetAsDirty( const BOARD_ITEM* aItem ); |
||||
|
|
||||
|
public: |
||||
|
|
||||
|
CN_CONNECTIVITY_ALGO(); |
||||
|
~CN_CONNECTIVITY_ALGO(); |
||||
|
|
||||
|
ITEM_MAP_ENTRY& ItemEntry( const BOARD_CONNECTED_ITEM* aItem ) |
||||
|
{ |
||||
|
return m_itemMap[ aItem ]; |
||||
|
} |
||||
|
|
||||
|
bool IsNetDirty( int aNet ) const |
||||
|
{ |
||||
|
return m_dirtyNets[ aNet ]; |
||||
|
} |
||||
|
|
||||
|
void ClearDirtyFlags() |
||||
|
{ |
||||
|
for( auto i = m_dirtyNets.begin(); i != m_dirtyNets.end(); ++i ) |
||||
|
*i = false; |
||||
|
} |
||||
|
|
||||
|
void GetDirtyClusters( CLUSTERS& aClusters ) |
||||
|
{ |
||||
|
for( auto cl : m_ratsnestClusters ) |
||||
|
{ |
||||
|
int net = cl->OriginNet(); |
||||
|
|
||||
|
if( net >= 0 && m_dirtyNets[net] ) |
||||
|
aClusters.push_back( cl ); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int NetCount() const |
||||
|
{ |
||||
|
return m_dirtyNets.size(); |
||||
|
} |
||||
|
|
||||
|
void Build( BOARD* aBoard ); |
||||
|
void Build( const std::vector<BOARD_ITEM*>& aItems ); |
||||
|
|
||||
|
void Clear(); |
||||
|
|
||||
|
bool Remove( BOARD_ITEM* aItem ); |
||||
|
bool Add( BOARD_ITEM* aItem ); |
||||
|
|
||||
|
const CLUSTERS SearchClusters( CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet ); |
||||
|
const CLUSTERS SearchClusters( CLUSTER_SEARCH_MODE aMode ); |
||||
|
|
||||
|
void PropagateNets(); |
||||
|
void FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands ); |
||||
|
bool CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport ); |
||||
|
|
||||
|
const CLUSTERS& GetClusters(); |
||||
|
int GetUnconnectedCount(); |
||||
|
}; |
||||
|
|
||||
|
bool operator<( const CN_ANCHOR_PTR a, const CN_ANCHOR_PTR b ); |
||||
|
|
||||
|
#endif |
||||
1510
pcbnew/ratsnest_data.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,809 @@ |
|||||
|
/*
|
||||
|
* This program source code file is part of KiCad, a free EDA CAD application. |
||||
|
* |
||||
|
* Copyright (C) 2013-2016 CERN |
||||
|
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. |
||||
|
* @author Maciej Suminski <maciej.suminski@cern.ch> |
||||
|
* |
||||
|
* 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 "common_actions.h"
|
||||
|
#include <tool/action_manager.h>
|
||||
|
#include <pcbnew_id.h>
|
||||
|
#include <layers_id_colors_and_visibility.h>
|
||||
|
#include <bitmaps.h>
|
||||
|
#include <wx/defs.h>
|
||||
|
#include <hotkeys.h>
|
||||
|
|
||||
|
// These members are static in class COMMON_ACTIONS: Build them here:
|
||||
|
|
||||
|
// Selection tool actions
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectionActivate( "pcbnew.InteractiveSelection", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "", NULL, AF_ACTIVATE ); // No description, it is not supposed to be shown anywhere
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectionCursor( "pcbnew.InteractiveSelection.Cursor", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); // No description, it is not supposed to be shown anywhere
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectItem( "pcbnew.InteractiveSelection.SelectItem", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); // No description, it is not supposed to be shown anywhere
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::unselectItem( "pcbnew.InteractiveSelection.UnselectItem", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); // No description, it is not supposed to be shown anywhere
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectionClear( "pcbnew.InteractiveSelection.Clear", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); // No description, it is not supposed to be shown anywhere
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectConnection( "pcbnew.InteractiveSelection.SelectConnection", |
||||
|
AS_GLOBAL, 'U', |
||||
|
_( "Trivial Connection" ), _( "Selects a connection between two junctions." ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectCopper( "pcbnew.InteractiveSelection.SelectCopper", |
||||
|
AS_GLOBAL, 'I', |
||||
|
_( "Copper Connection" ), _( "Selects whole copper connection." ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectNet( "pcbnew.InteractiveSelection.SelectNet", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Whole Net" ), _( "Selects all tracks & vias belonging to the same net." ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectSameSheet( "pcbnew.InteractiveSelection.SelectSameSheet", |
||||
|
AS_GLOBAL, 'P', |
||||
|
_( "Same Sheet" ), _( "Selects all modules and tracks in the same schematic sheet" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::find( "pcbnew.InteractiveSelection.Find", |
||||
|
AS_GLOBAL, 0, //TOOL_ACTION::LegacyHotKey( HK_FIND_ITEM ), // handled by wxWidgets
|
||||
|
_( "Find Item" ), _( "Searches the document for an item" ), find_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::findMove( "pcbnew.InteractiveSelection.FindMove", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_GET_AND_MOVE_FOOTPRINT ) ); |
||||
|
|
||||
|
|
||||
|
// Edit tool actions
|
||||
|
TOOL_ACTION COMMON_ACTIONS::editFootprintInFpEditor( "pcbnew.InteractiveEdit.editFootprintInFpEditor", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT_MODULE_WITH_MODEDIT ), |
||||
|
_( "Open in Footprint Editor" ), |
||||
|
_( "Opens the selected footprint in the Footprint Editor" ), |
||||
|
module_editor_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::copyPadToSettings( "pcbnew.InteractiveEdit.copyPadToSettings", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Copy Pad Settings to Current Settings" ), |
||||
|
_( "Copies the properties of selected pad to the current template pad settings." ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::copySettingsToPads( "pcbnew.InteractiveEdit.copySettingsToPads", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Copy Current Settings to Pads" ), |
||||
|
_( "Copies the current template pad settings to the selected pad(s)." ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::globalEditPads( "pcbnew.InteractiveEdit.globalPadEdit", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Global Pad Edition" ), |
||||
|
_( "Changes pad properties globally." ), push_pad_settings_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::editActivate( "pcbnew.InteractiveEdit", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_ITEM ), |
||||
|
_( "Move" ), _( "Moves the selected item(s)" ), move_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drag( "pcbnew.InteractiveEdit.dragItem", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ), |
||||
|
_( "Drag" ), _( "Drags the selected item(s)" ), drag_track_segment_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::duplicate( "pcbnew.InteractiveEdit.duplicate", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DUPLICATE_ITEM ), |
||||
|
_( "Duplicate" ), _( "Duplicates the selected item(s)" ), duplicate_module_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::duplicateIncrement( "pcbnew.InteractiveEdit.duplicateIncrementPads", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DUPLICATE_ITEM_AND_INCREMENT ), |
||||
|
_( "Duplicate" ), _( "Duplicates the selected item(s), incrementing pad numbers" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::moveExact( "pcbnew.InteractiveEdit.moveExact", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_MOVE_ITEM_EXACT ), |
||||
|
_( "Move Exactly..." ), _( "Moves the selected item(s) by an exact amount" ), |
||||
|
move_module_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::createArray( "pcbnew.InteractiveEdit.createArray", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_CREATE_ARRAY ), |
||||
|
_( "Create Array" ), _( "Create array" ), array_module_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::rotateCw( "pcbnew.InteractiveEdit.rotateCw", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ROTATE_ITEM ), |
||||
|
_( "Rotate Clockwise" ), _( "Rotates selected item(s) clockwise" ), |
||||
|
rotate_cw_xpm, AF_NONE, (void*) 1 ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::rotateCcw( "pcbnew.InteractiveEdit.rotateCcw", |
||||
|
AS_GLOBAL, MD_SHIFT + 'R', |
||||
|
_( "Rotate Counter-clockwise" ), _( "Rotates selected item(s) counter-clockwise" ), |
||||
|
rotate_ccw_xpm, AF_NONE, (void*) -1 ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::flip( "pcbnew.InteractiveEdit.flip", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_FLIP_ITEM ), |
||||
|
_( "Flip" ), _( "Flips selected item(s)" ), swap_layer_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::mirror( "pcbnew.InteractiveEdit.mirror", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Mirror" ), _( "Mirrors selected item" ), mirror_h_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::remove( "pcbnew.InteractiveEdit.remove", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_BACK_SPACE ), |
||||
|
_( "Remove" ), _( "Deletes selected item(s)" ), delete_xpm, |
||||
|
AF_NONE, (void*) REMOVE_FLAGS::NORMAL ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::removeAlt( "pcbnew.InteractiveEdit.removeAlt", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DELETE ), |
||||
|
_( "Remove (Alternative)" ), _( "Deletes selected item(s)" ), delete_xpm, |
||||
|
AF_NONE, (void*) REMOVE_FLAGS::ALT ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::exchangeFootprints( "pcbnew.InteractiveEdit.ExchangeFootprints", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Exchange Footprint(s)" ), _( "Change the footprint used for modules" ), |
||||
|
import_module_xpm ); |
||||
|
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::properties( "pcbnew.InteractiveEdit.properties", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_EDIT_ITEM ), |
||||
|
_( "Properties..." ), _( "Displays item properties dialog" ), editor_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::editModifiedSelection( "pcbnew.InteractiveEdit.ModifiedSelection", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
|
||||
|
// Drawing tool actions
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawLine( "pcbnew.InteractiveDrawing.line", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Draw Line" ), _( "Draw a line" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawCircle( "pcbnew.InteractiveDrawing.circle", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Draw Circle" ), _( "Draw a circle" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawArc( "pcbnew.InteractiveDrawing.arc", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Draw Arc" ), _( "Draw an arc" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::placeText( "pcbnew.InteractiveDrawing.text", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Text" ), _( "Add a text" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawDimension( "pcbnew.InteractiveDrawing.dimension", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Dimension" ), _( "Add a dimension" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawZone( "pcbnew.InteractiveDrawing.zone", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Filled Zone" ), _( "Add a filled zone" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawKeepout( "pcbnew.InteractiveDrawing.keepout", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Keepout Area" ), _( "Add a keepout area" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawZoneCutout( "pcbnew.InteractiveDrawing.zoneCutout", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add a Zone Cutout" ), _( "Add a cutout area of an existing zone" ), |
||||
|
add_zone_cutout_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drawSimilarZone( "pcbnew.InteractiveDrawing.similarZone", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add a Similar Zone" ), _( "Add a zone with the same settings as an existing zone" ), |
||||
|
add_zone_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::placeDXF( "pcbnew.InteractiveDrawing.placeDXF", |
||||
|
AS_GLOBAL, 0, |
||||
|
"Place DXF", "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::setAnchor( "pcbnew.InteractiveDrawing.setAnchor", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Place the Footprint Anchor" ), _( "Place the footprint anchor" ), |
||||
|
NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::incWidth( "pcbnew.InteractiveDrawing.incWidth", |
||||
|
AS_CONTEXT, '+', |
||||
|
_( "Increase Line Width" ), _( "Increase the line width" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::decWidth( "pcbnew.InteractiveDrawing.decWidth", |
||||
|
AS_CONTEXT, '-', |
||||
|
_( "Decrease Line Width" ), _( "Decrease the line width" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::arcPosture( "pcbnew.InteractiveDrawing.arcPosture", |
||||
|
AS_CONTEXT, TOOL_ACTION::LegacyHotKey( HK_SWITCH_TRACK_POSTURE ), |
||||
|
_( "Switch Arc Posture" ), _( "Switch the arc posture" ) ); |
||||
|
|
||||
|
|
||||
|
// View Controls
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomIn( "common.Control.zoomIn", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZOOM_IN ), |
||||
|
_( "Zoom In" ), "", zoom_in_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomOut( "common.Control.zoomOut", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZOOM_OUT ), |
||||
|
_( "Zoom Out" ), "", zoom_out_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomInCenter( "common.Control.zoomInCenter", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomOutCenter( "common.Control.zoomOutCenter", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomCenter( "common.Control.zoomCenter", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZOOM_CENTER ), |
||||
|
_( "Center" ), "", zoom_center_on_screen_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomFitScreen( "common.Control.zoomFitScreen", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZOOM_AUTO ), |
||||
|
_( "Zoom Auto" ), "", zoom_fit_in_page_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomPreset( "common.Control.zoomPreset", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
|
||||
|
// Display modes
|
||||
|
TOOL_ACTION COMMON_ACTIONS::trackDisplayMode( "pcbnew.Control.trackDisplayMode", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_TRACK_DISPLAY_MODE ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::padDisplayMode( "pcbnew.Control.padDisplayMode", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::viaDisplayMode( "pcbnew.Control.viaDisplayMode", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneDisplayEnable( "pcbnew.Control.zoneDisplayEnable", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneDisplayDisable( "pcbnew.Control.zoneDisplayDisable", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneDisplayOutlines( "pcbnew.Control.zoneDisplayOutlines", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::highContrastMode( "pcbnew.Control.highContrastMode", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_HIGHCONTRAST_MODE ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::highContrastInc( "pcbnew.Control.highContrastInc", |
||||
|
AS_GLOBAL, '>', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::highContrastDec( "pcbnew.Control.highContrastDec", |
||||
|
AS_GLOBAL, '<', |
||||
|
"", "" ); |
||||
|
|
||||
|
|
||||
|
// Layer control
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerTop( "pcbnew.Control.layerTop", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_COMPONENT ), |
||||
|
"", "", NULL, AF_NONE, (void*) F_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner1( "pcbnew.Control.layerInner1", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER1 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In1_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner2( "pcbnew.Control.layerInner2", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER2 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In2_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner3( "pcbnew.Control.layerInner3", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER3 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In3_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner4( "pcbnew.Control.layerInner4", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER4 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In4_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner5( "pcbnew.Control.layerInner5", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER5 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In5_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerInner6( "pcbnew.Control.layerInner6", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_INNER6 ), |
||||
|
"", "", NULL, AF_NONE, (void*) In6_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerBottom( "pcbnew.Control.layerBottom", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_COPPER ), |
||||
|
"", "", NULL, AF_NONE, (void*) B_Cu ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerNext( "pcbnew.Control.layerNext", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_NEXT ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerPrev( "pcbnew.Control.layerPrev", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_LAYER_TO_PREVIOUS ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerToggle( "pcbnew.Control.layerToggle", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_THROUGH_VIA ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerAlphaInc( "pcbnew.Control.layerAlphaInc", |
||||
|
AS_GLOBAL, '}', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerAlphaDec( "pcbnew.Control.layerAlphaDec", |
||||
|
AS_GLOBAL, '{', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::layerChanged( "pcbnew.Control.layerChanged", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "", NULL, AF_NOTIFY ); |
||||
|
|
||||
|
|
||||
|
// Grid control
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridFast1( "common.Control.gridFast1", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_GRID_TO_FASTGRID1 ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridFast2( "common.Control.gridFast2", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_GRID_TO_FASTGRID2 ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridNext( "common.Control.gridNext", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_GRID_TO_NEXT ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridPrev( "common.Control.gridPrev", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_GRID_TO_PREVIOUS ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridSetOrigin( "common.Control.gridSetOrigin", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SET_GRID_ORIGIN ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridResetOrigin( "common.Control.gridResetOrigin", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_RESET_GRID_ORIGIN ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::gridPreset( "common.Control.gridPreset", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
// Track & via size control
|
||||
|
TOOL_ACTION COMMON_ACTIONS::trackWidthInc( "pcbnew.EditorControl.trackWidthInc", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_TRACK_WIDTH_TO_NEXT ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::trackWidthDec( "pcbnew.EditorControl.trackWidthDec", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_TRACK_WIDTH_TO_PREVIOUS ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::viaSizeInc( "pcbnew.EditorControl.viaSizeInc", |
||||
|
AS_GLOBAL, '\'', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::viaSizeDec( "pcbnew.EditorControl.viaSizeDec", |
||||
|
AS_GLOBAL, '\\', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::trackViaSizeChanged( "pcbnew.EditorControl.trackViaSizeChanged", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "", NULL, AF_NOTIFY ); |
||||
|
|
||||
|
|
||||
|
// Zone actions
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneFill( "pcbnew.EditorControl.zoneFill", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Fill" ), _( "Fill zone(s)" ), fill_zone_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneFillAll( "pcbnew.EditorControl.zoneFillAll", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_FILL_OR_REFILL ), |
||||
|
_( "Fill All" ), _( "Fill all zones" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneUnfill( "pcbnew.EditorControl.zoneUnfill", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Unfill" ), _( "Unfill zone(s)" ), zone_unfill_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneUnfillAll( "pcbnew.EditorControl.zoneUnfillAll", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZONE_REMOVE_FILLED ), |
||||
|
_( "Unfill All" ), _( "Unfill all zones" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneMerge( "pcbnew.EditorControl.zoneMerge", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Merge Zones" ), _( "Merge zones" ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoneDuplicate( "pcbnew.EditorControl.zoneDuplicate", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Duplicate Zone onto Layer" ), _( "Duplicate zone outline onto a different layer" ), |
||||
|
zone_duplicate_xpm ); |
||||
|
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::placeTarget( "pcbnew.EditorControl.placeTarget", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Layer Alignment Target" ), _( "Add a layer alignment target" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::placeModule( "pcbnew.EditorControl.placeModule", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_MODULE ), |
||||
|
_( "Add Footprint" ), _( "Add a footprint" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::drillOrigin( "pcbnew.EditorControl.drillOrigin", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::crossProbeSchToPcb( "pcbnew.EditorControl.crossProbSchToPcb", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::toggleLock( "pcbnew.EditorControl.toggleLock", |
||||
|
AS_GLOBAL, 'L', |
||||
|
"Toggle Lock", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::lock( "pcbnew.EditorControl.lock", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Lock" ), "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::unlock( "pcbnew.EditorControl.unlock", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Unlock" ), "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::appendBoard( "pcbnew.EditorControl.appendBoard", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::highlightNet( "pcbnew.EditorControl.highlightNet", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::highlightNetCursor( "pcbnew.EditorControl.highlightNetCursor", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
|
||||
|
// Module editor tools
|
||||
|
TOOL_ACTION COMMON_ACTIONS::placePad( "pcbnew.ModuleEditor.placePad", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Add Pad" ), _( "Add a pad" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::enumeratePads( "pcbnew.ModuleEditor.enumeratePads", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Enumerate Pads" ), _( "Enumerate pads" ), pad_enumerate_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::copyItems( "pcbnew.ModuleEditor.copyItems", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_COPY_ITEM ), |
||||
|
_( "Copy" ), _( "Copy items" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::pasteItems( "pcbnew.ModuleEditor.pasteItems", |
||||
|
AS_GLOBAL, MD_CTRL + int( 'V' ), |
||||
|
_( "Paste" ), _( "Paste items" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::moduleEdgeOutlines( "pcbnew.ModuleEditor.graphicOutlines", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::moduleTextOutlines( "pcbnew.ModuleEditor.textOutlines", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
// Pad tools
|
||||
|
TOOL_ACTION COMMON_ACTIONS::copyPadSettings( |
||||
|
"pcbnew.PadTool.CopyPadSettings", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Copy Pad Settings" ), _( "Copy current pad's settings to the board design settings" ), |
||||
|
copy_pad_settings_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::applyPadSettings( |
||||
|
"pcbnew.PadTool.ApplyPadSettings", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Apply Pad Settings" ), _( "Copy the board design settings pad properties to the current pad" ), |
||||
|
apply_pad_settings_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::pushPadSettings( |
||||
|
"pcbnew.PadTool.PushPadSettings", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Push Pad Settings" ), _( "Copy the current pad settings to other pads" ), |
||||
|
push_pad_settings_xpm ); |
||||
|
|
||||
|
// Cursor control
|
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorUp( "pcbnew.Control.cursorUp", |
||||
|
AS_GLOBAL, WXK_UP, "", "", NULL, AF_NONE, (void*) CURSOR_UP ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorDown( "pcbnew.Control.cursorDown", |
||||
|
AS_GLOBAL, WXK_DOWN, "", "" , NULL, AF_NONE, (void*) CURSOR_DOWN ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorLeft( "pcbnew.Control.cursorLeft", |
||||
|
AS_GLOBAL, WXK_LEFT, "", "" , NULL, AF_NONE, (void*) CURSOR_LEFT ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorRight( "pcbnew.Control.cursorRight", |
||||
|
AS_GLOBAL, WXK_RIGHT, "", "" , NULL, AF_NONE, (void*) CURSOR_RIGHT ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorUpFast( "pcbnew.Control.cursorUpFast", |
||||
|
AS_GLOBAL, MD_CTRL + WXK_UP, "", "", NULL, AF_NONE, (void*) ( CURSOR_UP | CURSOR_FAST_MOVE ) ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorDownFast( "pcbnew.Control.cursorDownFast", |
||||
|
AS_GLOBAL, MD_CTRL + WXK_DOWN, "", "" , NULL, AF_NONE, (void*) ( CURSOR_DOWN | CURSOR_FAST_MOVE ) ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorLeftFast( "pcbnew.Control.cursorLeftFast", |
||||
|
AS_GLOBAL, MD_CTRL + WXK_LEFT, "", "" , NULL, AF_NONE, (void*) ( CURSOR_LEFT | CURSOR_FAST_MOVE ) ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorRightFast( "pcbnew.Control.cursorRightFast", |
||||
|
AS_GLOBAL, MD_CTRL + WXK_RIGHT, "", "" , NULL, AF_NONE, (void*) ( CURSOR_RIGHT | CURSOR_FAST_MOVE ) ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorClick( "pcbnew.Control.cursorClick", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_LEFT_CLICK ), |
||||
|
"", "", NULL, AF_NONE, (void*) CURSOR_CLICK ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::cursorDblClick( "pcbnew.Control.cursorDblClick", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_LEFT_DCLICK ), |
||||
|
"", "", NULL, AF_NONE, (void*) CURSOR_DBL_CLICK ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::panUp( "pcbnew.Control.panUp", |
||||
|
AS_GLOBAL, MD_SHIFT + WXK_UP, "", "", NULL, AF_NONE, (void*) CURSOR_UP ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::panDown( "pcbnew.Control.panDown", |
||||
|
AS_GLOBAL, MD_SHIFT + WXK_DOWN, "", "" , NULL, AF_NONE, (void*) CURSOR_DOWN ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::panLeft( "pcbnew.Control.panLeft", |
||||
|
AS_GLOBAL, MD_SHIFT + WXK_LEFT, "", "" , NULL, AF_NONE, (void*) CURSOR_LEFT ); |
||||
|
TOOL_ACTION COMMON_ACTIONS::panRight( "pcbnew.Control.panRight", |
||||
|
AS_GLOBAL, MD_SHIFT + WXK_RIGHT, "", "" , NULL, AF_NONE, (void*) CURSOR_RIGHT ); |
||||
|
|
||||
|
// Miscellaneous
|
||||
|
TOOL_ACTION COMMON_ACTIONS::selectionTool( "pcbnew.Control.selectionTool", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::zoomTool( "pcbnew.Control.zoomTool", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ZOOM_SELECTION ), |
||||
|
_( "Zoom to Selection" ), "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::pickerTool( "pcbnew.Picker", AS_GLOBAL, 0, "", "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::resetCoords( "pcbnew.Control.resetCoords", |
||||
|
AS_GLOBAL, ' ', |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::switchCursor( "pcbnew.Control.switchCursor", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::switchUnits( "pcbnew.Control.switchUnits", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_SWITCH_UNITS ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::deleteItemCursor( "pcbnew.Control.deleteItemCursor", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::showHelp( "pcbnew.Control.showHelp", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_HELP ), |
||||
|
"", "" ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::toBeDone( "pcbnew.Control.toBeDone", |
||||
|
AS_GLOBAL, 0, // dialog saying it is not implemented yet
|
||||
|
"", "" ); // so users are aware of that
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::showLocalRatsnest( "pcbnew.Control.showLocalRatsnest", |
||||
|
AS_GLOBAL, 0, |
||||
|
"", "" ); |
||||
|
|
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateSingle( "pcbnew.InteractiveRouter.SingleTrack", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_ADD_NEW_TRACK ), |
||||
|
_( "Interactive Router (Single Tracks)" ), |
||||
|
_( "Run push & shove router (single tracks)" ), ps_router_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateDiffPair( "pcbnew.InteractiveRouter.DiffPair", |
||||
|
AS_GLOBAL, '6', |
||||
|
_( "Interactive Router (Differential Pairs)" ), |
||||
|
_( "Run push & shove router (differential pairs)" ), ps_diff_pair_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateSettingsDialog( "pcbnew.InteractiveRouter.SettingsDialog", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Interactive Router Settings" ), |
||||
|
_( "Open Interactive Router settings" ), NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateDpDimensionsDialog( "pcbnew.InteractiveRouter.DpDimensionsDialog", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Differential Pair Dimension settings" ), |
||||
|
_( "Open Differential Pair Dimension settings" ), ps_diff_pair_gap_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateTuneSingleTrace( "pcbnew.LengthTuner.TuneSingleTrack", |
||||
|
AS_GLOBAL, '7', |
||||
|
_( "Tune length of a single track" ), "", ps_tune_length_xpm, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateTuneDiffPair( "pcbnew.LengthTuner.TuneDiffPair", |
||||
|
AS_GLOBAL, '8', |
||||
|
_( "Tune length of a differential pair" ), "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerActivateTuneDiffPairSkew( "pcbnew.LengthTuner.TuneDiffPairSkew", |
||||
|
AS_GLOBAL, '9', |
||||
|
_( "Tune skew of a differential pair" ), "", NULL, AF_ACTIVATE ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::routerInlineDrag( "pcbnew.InteractiveRouter.InlineDrag", |
||||
|
AS_GLOBAL, TOOL_ACTION::LegacyHotKey( HK_DRAG_TRACK_KEEP_SLOPE ), |
||||
|
_( "Drag Track/Via" ), _( "Drags tracks and vias without breaking connections" ), |
||||
|
drag_track_segment_xpm ); |
||||
|
|
||||
|
// Point editor
|
||||
|
TOOL_ACTION COMMON_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Create Corner" ), _( "Create a corner" ), add_corner_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::pointEditorRemoveCorner( "pcbnew.PointEditor.removeCorner", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Remove Corner" ), _( "Remove corner" ), delete_xpm ); |
||||
|
|
||||
|
// Placement tool
|
||||
|
TOOL_ACTION COMMON_ACTIONS::alignTop( "pcbnew.Place.alignTop", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Align to Top" ), |
||||
|
_( "Aligns selected items to the top edge" ), up_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::alignBottom( "pcbnew.Place.alignBottom", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Align to Bottom" ), |
||||
|
_( "Aligns selected items to the bottom edge" ), down_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::alignLeft( "pcbnew.Place.alignLeft", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Align to Left" ), |
||||
|
_( "Aligns selected items to the left edge" ), left_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::alignRight( "pcbnew.Place.alignRight", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Align to Right" ), |
||||
|
_( "Aligns selected items to the right edge" ), right_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::distributeHorizontally( "pcbnew.Place.distributeHorizontally", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Distribute Horizontally" ), |
||||
|
_( "Distributes selected items along the horizontal axis" ), distribute_horizontal_xpm ); |
||||
|
|
||||
|
TOOL_ACTION COMMON_ACTIONS::distributeVertically( "pcbnew.Place.distributeVertically", |
||||
|
AS_GLOBAL, 0, |
||||
|
_( "Distribute Vertically" ), |
||||
|
_( "Distributes selected items along the vertical axis" ), distribute_vertical_xpm ); |
||||
|
|
||||
|
|
||||
|
boost::optional<TOOL_EVENT> COMMON_ACTIONS::TranslateLegacyId( int aId ) |
||||
|
{ |
||||
|
switch( aId ) |
||||
|
{ |
||||
|
case ID_PCB_MODULE_BUTT: |
||||
|
return COMMON_ACTIONS::placeModule.MakeEvent(); |
||||
|
|
||||
|
case ID_TRACK_BUTT: |
||||
|
return COMMON_ACTIONS::routerActivateSingle.MakeEvent(); |
||||
|
|
||||
|
case ID_DIFF_PAIR_BUTT: |
||||
|
return COMMON_ACTIONS::routerActivateDiffPair.MakeEvent(); |
||||
|
|
||||
|
case ID_TUNE_SINGLE_TRACK_LEN_BUTT: |
||||
|
return COMMON_ACTIONS::routerActivateTuneSingleTrace.MakeEvent(); |
||||
|
|
||||
|
case ID_TUNE_DIFF_PAIR_LEN_BUTT: |
||||
|
return COMMON_ACTIONS::routerActivateTuneDiffPair.MakeEvent(); |
||||
|
|
||||
|
case ID_TUNE_DIFF_PAIR_SKEW_BUTT: |
||||
|
return COMMON_ACTIONS::routerActivateTuneDiffPairSkew.MakeEvent(); |
||||
|
|
||||
|
case ID_MENU_INTERACTIVE_ROUTER_SETTINGS: |
||||
|
return COMMON_ACTIONS::routerActivateSettingsDialog.MakeEvent(); |
||||
|
|
||||
|
case ID_MENU_DIFF_PAIR_DIMENSIONS: |
||||
|
return COMMON_ACTIONS::routerActivateDpDimensionsDialog.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_ZONES_BUTT: |
||||
|
return COMMON_ACTIONS::drawZone.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_KEEPOUT_AREA_BUTT: |
||||
|
return COMMON_ACTIONS::drawKeepout.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_ADD_LINE_BUTT: |
||||
|
case ID_MODEDIT_LINE_TOOL: |
||||
|
return COMMON_ACTIONS::drawLine.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_CIRCLE_BUTT: |
||||
|
case ID_MODEDIT_CIRCLE_TOOL: |
||||
|
return COMMON_ACTIONS::drawCircle.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_ARC_BUTT: |
||||
|
case ID_MODEDIT_ARC_TOOL: |
||||
|
return COMMON_ACTIONS::drawArc.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_ADD_TEXT_BUTT: |
||||
|
case ID_MODEDIT_TEXT_TOOL: |
||||
|
return COMMON_ACTIONS::placeText.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_DIMENSION_BUTT: |
||||
|
return COMMON_ACTIONS::drawDimension.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_MIRE_BUTT: |
||||
|
return COMMON_ACTIONS::placeTarget.MakeEvent(); |
||||
|
|
||||
|
case ID_MODEDIT_PAD_TOOL: |
||||
|
return COMMON_ACTIONS::placePad.MakeEvent(); |
||||
|
|
||||
|
case ID_GEN_IMPORT_DXF_FILE: |
||||
|
return COMMON_ACTIONS::placeDXF.MakeEvent(); |
||||
|
|
||||
|
case ID_MODEDIT_ANCHOR_TOOL: |
||||
|
return COMMON_ACTIONS::setAnchor.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_PLACE_GRID_COORD_BUTT: |
||||
|
case ID_MODEDIT_PLACE_GRID_COORD: |
||||
|
return COMMON_ACTIONS::gridSetOrigin.MakeEvent(); |
||||
|
|
||||
|
case ID_ZOOM_IN: // toolbar button "Zoom In"
|
||||
|
return COMMON_ACTIONS::zoomInCenter.MakeEvent(); |
||||
|
|
||||
|
case ID_ZOOM_OUT: // toolbar button "Zoom In"
|
||||
|
return COMMON_ACTIONS::zoomOutCenter.MakeEvent(); |
||||
|
|
||||
|
case ID_ZOOM_PAGE: // toolbar button "Fit on Screen"
|
||||
|
return COMMON_ACTIONS::zoomFitScreen.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_TRACKS_SKETCH: |
||||
|
return COMMON_ACTIONS::trackDisplayMode.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_PADS_SKETCH: |
||||
|
return COMMON_ACTIONS::padDisplayMode.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_VIAS_SKETCH: |
||||
|
return COMMON_ACTIONS::viaDisplayMode.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_ZONES: |
||||
|
return COMMON_ACTIONS::zoneDisplayEnable.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_ZONES_DISABLE: |
||||
|
return COMMON_ACTIONS::zoneDisplayDisable.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_ZONES_OUTLINES_ONLY: |
||||
|
return COMMON_ACTIONS::zoneDisplayOutlines.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_MODULE_EDGE_SKETCH: |
||||
|
return COMMON_ACTIONS::moduleEdgeOutlines.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_MODULE_TEXT_SKETCH: |
||||
|
return COMMON_ACTIONS::moduleTextOutlines.MakeEvent(); |
||||
|
|
||||
|
case ID_TB_OPTIONS_SHOW_HIGH_CONTRAST_MODE: |
||||
|
return COMMON_ACTIONS::highContrastMode.MakeEvent(); |
||||
|
|
||||
|
case ID_FIND_ITEMS: |
||||
|
return COMMON_ACTIONS::find.MakeEvent(); |
||||
|
|
||||
|
case ID_POPUP_PCB_GET_AND_MOVE_MODULE_REQUEST: |
||||
|
return COMMON_ACTIONS::findMove.MakeEvent(); |
||||
|
|
||||
|
case ID_NO_TOOL_SELECTED: |
||||
|
return COMMON_ACTIONS::selectionTool.MakeEvent(); |
||||
|
|
||||
|
case ID_ZOOM_SELECTION: |
||||
|
return COMMON_ACTIONS::zoomTool.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_DELETE_ITEM_BUTT: |
||||
|
case ID_MODEDIT_DELETE_TOOL: |
||||
|
return COMMON_ACTIONS::deleteItemCursor.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_PLACE_OFFSET_COORD_BUTT: |
||||
|
return COMMON_ACTIONS::drillOrigin.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_HIGHLIGHT_BUTT: |
||||
|
return COMMON_ACTIONS::highlightNetCursor.MakeEvent(); |
||||
|
|
||||
|
case ID_APPEND_FILE: |
||||
|
return COMMON_ACTIONS::appendBoard.MakeEvent(); |
||||
|
|
||||
|
case ID_PCB_SHOW_1_RATSNEST_BUTT: |
||||
|
return COMMON_ACTIONS::showLocalRatsnest.MakeEvent(); |
||||
|
} |
||||
|
|
||||
|
return boost::optional<TOOL_EVENT>(); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue