New connectivity algorithm.
This commit is contained in:
parent
eaba60b89a
commit
9ad886344b
|
@ -1138,6 +1138,7 @@ void EDA_DRAW_FRAME::UseGalCanvas( bool aEnable )
|
|||
gal->SetGridOrigin( VECTOR2D( GetGridOrigin() ) );
|
||||
|
||||
// Transfer EDA_DRAW_PANEL settings
|
||||
|
||||
GetGalCanvas()->GetViewControls()->EnableCursorWarping( !m_canvas->GetEnableZoomNoCenter() );
|
||||
GetGalCanvas()->GetViewControls()->EnableMousewheelPan( m_canvas->GetEnableMousewheelPan() );
|
||||
}
|
||||
|
@ -1365,4 +1366,3 @@ void EDA_DRAW_FRAME::GeneralControlKeyMovement( int aHotKey, wxPoint *aPos,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,14 +55,6 @@ using namespace hed;
|
|||
#endif
|
||||
|
||||
|
||||
void NODE::updateLayers()
|
||||
{
|
||||
assert( m_layers.none() );
|
||||
|
||||
for( const BOARD_CONNECTED_ITEM* item : m_parents )
|
||||
m_layers |= item->GetLayerSet();
|
||||
}
|
||||
|
||||
|
||||
//#define DEBUG_HE
|
||||
#ifdef DEBUG_HE
|
||||
|
@ -402,12 +394,11 @@ std::list<NODE_PTR>* TRIANGULATION::GetNodes() const
|
|||
#endif
|
||||
|
||||
|
||||
std::list<EDGE_PTR>* TRIANGULATION::GetEdges( bool aSkipBoundaryEdges ) const
|
||||
void TRIANGULATION::GetEdges( std::list<EDGE_PTR>& aEdges, bool aSkipBoundaryEdges ) const
|
||||
{
|
||||
// collect all arcs (one half edge for each arc)
|
||||
// (boundary edges are also collected).
|
||||
std::list<EDGE_PTR>::const_iterator it;
|
||||
std::list<EDGE_PTR>* elist = new std::list<EDGE_PTR>;
|
||||
|
||||
for( it = m_leadingEdges.begin(); it != m_leadingEdges.end(); ++it )
|
||||
{
|
||||
|
@ -419,13 +410,13 @@ std::list<EDGE_PTR>* TRIANGULATION::GetEdges( bool aSkipBoundaryEdges ) const
|
|||
|
||||
if( ( !twinedge && !aSkipBoundaryEdges )
|
||||
|| ( twinedge && ( (size_t) edge.get() > (size_t) twinedge.get() ) ) )
|
||||
elist->push_front( edge );
|
||||
{
|
||||
aEdges.push_front( edge );
|
||||
}
|
||||
|
||||
edge = edge->GetNextEdgeInFace();
|
||||
}
|
||||
}
|
||||
|
||||
return elist;
|
||||
}
|
||||
|
||||
|
||||
|
@ -613,7 +604,8 @@ void TRIANGULATION::OptimizeDelaunay()
|
|||
|
||||
// Collect all interior edges (one half edge for each arc)
|
||||
bool skip_boundary_edges = true;
|
||||
std::list<EDGE_PTR>* elist = GetEdges( skip_boundary_edges );
|
||||
std::list<EDGE_PTR> elist;
|
||||
GetEdges( elist, skip_boundary_edges );
|
||||
|
||||
// Assumes that elist has only one half-edge for each arc.
|
||||
bool cycling_check = true;
|
||||
|
@ -624,7 +616,7 @@ void TRIANGULATION::OptimizeDelaunay()
|
|||
{
|
||||
optimal = true;
|
||||
|
||||
for( it = elist->begin(); it != elist->end(); ++it )
|
||||
for( it = elist.begin(); it != elist.end(); ++it )
|
||||
{
|
||||
EDGE_PTR edge = *it;
|
||||
|
||||
|
@ -637,8 +629,6 @@ void TRIANGULATION::OptimizeDelaunay()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete elist;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ void ACTION_MANAGER::UpdateHotKeys()
|
|||
++global_actions_cnt;
|
||||
}
|
||||
|
||||
assert( global_actions_cnt <= 1 );
|
||||
// assert( global_actions_cnt <= 1 );
|
||||
}
|
||||
#endif /* not NDEBUG */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
update=13/08/2016 16:32:14
|
||||
update=pią, 7 paź 2016, 14:28:36
|
||||
version=1
|
||||
last_client=kicad
|
||||
last_client=eeschema
|
||||
[general]
|
||||
version=1
|
||||
RootSch=
|
||||
|
@ -29,4 +29,84 @@ version=1
|
|||
NetIExt=net
|
||||
[eeschema]
|
||||
version=1
|
||||
LibDir=
|
||||
LibDir=/home/twl/Kicad-dev/kicad-library/library
|
||||
[eeschema/libraries]
|
||||
LibName1=74xgxx
|
||||
LibName2=74xx
|
||||
LibName3=ac-dc
|
||||
LibName4=actel
|
||||
LibName5=AD8051
|
||||
LibName6=adc-dac
|
||||
LibName7=Altera
|
||||
LibName8=analog_devices
|
||||
LibName9=analog_switches
|
||||
LibName10=atmel
|
||||
LibName11=audio
|
||||
LibName12=bbd
|
||||
LibName13=brooktre
|
||||
LibName14=cmos4000
|
||||
LibName15=cmos_ieee
|
||||
LibName16=conn
|
||||
LibName17=contrib
|
||||
LibName18=cypress
|
||||
LibName19=dc-dc
|
||||
LibName20=device
|
||||
LibName21=digital-audio
|
||||
LibName22=diode
|
||||
LibName23=display
|
||||
LibName24=dsp
|
||||
LibName25=elec-unifil
|
||||
LibName26=ESD_Protection
|
||||
LibName27=ftdi
|
||||
LibName28=gennum
|
||||
LibName29=graphic
|
||||
LibName30=hc11
|
||||
LibName31=intel
|
||||
LibName32=interface
|
||||
LibName33=ir
|
||||
LibName34=Lattice
|
||||
LibName35=linear
|
||||
LibName36=logo
|
||||
LibName37=maxim
|
||||
LibName38=memory
|
||||
LibName39=microchip
|
||||
LibName40=microchip_dspic33dsc
|
||||
LibName41=microchip_pic10mcu
|
||||
LibName42=microchip_pic12mcu
|
||||
LibName43=microchip_pic16mcu
|
||||
LibName44=microchip_pic18mcu
|
||||
LibName45=microchip_pic32mcu
|
||||
LibName46=microcontrollers
|
||||
LibName47=motor_drivers
|
||||
LibName48=motorola
|
||||
LibName49=msp430
|
||||
LibName50=nordicsemi
|
||||
LibName51=nxp_armmcu
|
||||
LibName52=onsemi
|
||||
LibName53=opto
|
||||
LibName54=Oscillators
|
||||
LibName55=philips
|
||||
LibName56=power
|
||||
LibName57=powerint
|
||||
LibName58=Power_Management
|
||||
LibName59=references
|
||||
LibName60=regul
|
||||
LibName61=relays
|
||||
LibName62=rfcom
|
||||
LibName63=sensors
|
||||
LibName64=silabs
|
||||
LibName65=siliconi
|
||||
LibName66=stm8
|
||||
LibName67=stm32
|
||||
LibName68=supertex
|
||||
LibName69=switches
|
||||
LibName70=texas
|
||||
LibName71=transf
|
||||
LibName72=transistors
|
||||
LibName73=ttl_ieee
|
||||
LibName74=valves
|
||||
LibName75=video
|
||||
LibName76=Worldsemi
|
||||
LibName77=Xicor
|
||||
LibName78=xilinx
|
||||
LibName79=Zilog
|
||||
|
|
|
@ -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
|
|
@ -601,6 +601,7 @@ public:
|
|||
}
|
||||
|
||||
const VECTOR2I PointAlong( int aPathLength ) const;
|
||||
const SHAPE_LINE_CHAIN RemoveHoles( ) const;
|
||||
|
||||
private:
|
||||
/// array of vertices
|
||||
|
|
|
@ -37,9 +37,6 @@
|
|||
#include <iomanip>
|
||||
#include <wx/log.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* The class PROF_COUNTER is a small class to help profiling.
|
||||
* It allows the calculation of the elapsed time (in millisecondes) between
|
||||
|
@ -154,41 +151,4 @@ private:
|
|||
*/
|
||||
unsigned GetRunningMicroSecs();
|
||||
|
||||
class PROF_COUNTER
|
||||
{
|
||||
public:
|
||||
PROF_COUNTER(const std::string& name, bool autostart = true)
|
||||
{
|
||||
m_name = name;
|
||||
m_running= false;
|
||||
if(autostart)
|
||||
start();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
m_running = true;
|
||||
prof_start(&m_cnt);
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if(!m_running)
|
||||
return;
|
||||
m_running=false;
|
||||
prof_end(&m_cnt);
|
||||
}
|
||||
|
||||
void show()
|
||||
{
|
||||
stop();
|
||||
fprintf(stderr,"%s took %.1f milliseconds.\n", m_name.c_str(), (double)m_cnt.msecs());
|
||||
}
|
||||
private:
|
||||
std::string m_name;
|
||||
prof_counter m_cnt;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
DART( const EDGE_PTR& aEdge, bool aDir = true )
|
||||
{
|
||||
m_edge = aEdge;
|
||||
assert ( m_edge );
|
||||
m_dir = aDir;
|
||||
}
|
||||
|
||||
|
@ -76,6 +77,7 @@ public:
|
|||
DART( const DART& aDart )
|
||||
{
|
||||
m_edge = aDart.m_edge;
|
||||
assert ( m_edge );
|
||||
m_dir = aDart.m_dir;
|
||||
}
|
||||
|
||||
|
@ -91,6 +93,7 @@ public:
|
|||
return *this;
|
||||
|
||||
m_edge = aDart.m_edge;
|
||||
assert ( m_edge );
|
||||
m_dir = aDart.m_dir;
|
||||
|
||||
return *this;
|
||||
|
@ -121,11 +124,13 @@ public:
|
|||
if( m_dir )
|
||||
{
|
||||
m_edge = m_edge->GetNextEdgeInFace()->GetNextEdgeInFace();
|
||||
assert ( m_edge );
|
||||
m_dir = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_edge = m_edge->GetNextEdgeInFace();
|
||||
assert ( m_edge );
|
||||
m_dir = true;
|
||||
}
|
||||
|
||||
|
@ -138,6 +143,7 @@ public:
|
|||
if( m_edge->GetTwinEdge() )
|
||||
{
|
||||
m_edge = m_edge->GetTwinEdge();
|
||||
assert ( m_edge );
|
||||
m_dir = !m_dir;
|
||||
}
|
||||
|
||||
|
@ -150,6 +156,7 @@ public:
|
|||
void Init( const EDGE_PTR& aEdge, bool aDir = true )
|
||||
{
|
||||
m_edge = aEdge;
|
||||
assert(m_edge);
|
||||
m_dir = aDir;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@
|
|||
#ifndef _HE_TRIANG_H_
|
||||
#define _HE_TRIANG_H_
|
||||
|
||||
//#define TTL_USE_NODE_ID // Each node gets it's own unique id
|
||||
//#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
|
||||
#define TTL_USE_NODE_ID // Each node gets it's own unique id
|
||||
#define TTL_USE_NODE_FLAG // Each node gets a flag (can be set to true or false)
|
||||
|
||||
#include <list>
|
||||
#include <unordered_set>
|
||||
|
@ -53,8 +53,10 @@
|
|||
#include <ttl/ttl_util.h>
|
||||
#include <memory>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <math/vector2d.h>
|
||||
|
||||
class BOARD_CONNECTED_ITEM;
|
||||
class CN_CLUSTER;
|
||||
|
||||
namespace ttl
|
||||
{
|
||||
|
@ -103,37 +105,25 @@ protected:
|
|||
/// Node coordinates
|
||||
const int m_x, m_y;
|
||||
|
||||
/// Tag for quick connection resolution
|
||||
int m_tag;
|
||||
|
||||
/// Whether it the node can be a target for ratsnest lines
|
||||
bool m_noline;
|
||||
|
||||
/// List of board items that share this node
|
||||
std::unordered_set<const BOARD_CONNECTED_ITEM*> m_parents;
|
||||
|
||||
/// Layers that are occupied by this node
|
||||
LSET m_layers;
|
||||
|
||||
/// Recomputes the layers used by this node
|
||||
void updateLayers();
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
NODE( int aX = 0, int aY = 0 ) :
|
||||
NODE( int aX = 0, int aY = 0, std::shared_ptr<CN_CLUSTER> aCluster = nullptr ) :
|
||||
#ifdef TTL_USE_NODE_FLAG
|
||||
m_flag( false ),
|
||||
#endif
|
||||
#ifdef TTL_USE_NODE_ID
|
||||
m_id( id_count++ ),
|
||||
#endif
|
||||
m_x( aX ), m_y( aY ), m_tag( -1 ), m_noline( false )
|
||||
m_x( aX ), m_y( aY )
|
||||
{
|
||||
m_layers.reset();
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
~NODE() {}
|
||||
~NODE() {
|
||||
|
||||
}
|
||||
|
||||
const VECTOR2D Pos() const { return VECTOR2D( m_x, m_y ); }
|
||||
|
||||
/// Returns the x-coordinate
|
||||
inline int GetX() const
|
||||
|
@ -147,32 +137,19 @@ public:
|
|||
return m_y;
|
||||
}
|
||||
|
||||
/// Returns tag, common identifier for connected nodes
|
||||
inline int GetTag() const
|
||||
inline VECTOR2I GetPos() 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;
|
||||
return VECTOR2I( m_x, m_y );
|
||||
}
|
||||
|
||||
#ifdef TTL_USE_NODE_ID
|
||||
/// Returns the id (TTL_USE_NODE_ID must be defined)
|
||||
|
||||
inline void SetId( int aId )
|
||||
{
|
||||
m_id = aId;
|
||||
}
|
||||
|
||||
inline int Id() const
|
||||
{
|
||||
return m_id;
|
||||
|
@ -192,39 +169,6 @@ public:
|
|||
return m_flag;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline unsigned int GetRefCount() const
|
||||
{
|
||||
return m_parents.size();
|
||||
}
|
||||
|
||||
inline void AddParent( const BOARD_CONNECTED_ITEM* aParent )
|
||||
{
|
||||
m_parents.insert( aParent );
|
||||
m_layers.reset(); // mark as needs updating
|
||||
}
|
||||
|
||||
inline void RemoveParent( const BOARD_CONNECTED_ITEM* aParent )
|
||||
{
|
||||
auto it = m_parents.find( aParent );
|
||||
|
||||
if( it != m_parents.end() )
|
||||
{
|
||||
m_parents.erase( it );
|
||||
m_layers.reset(); // mark as needs updating
|
||||
}
|
||||
}
|
||||
|
||||
const LSET& GetLayers()
|
||||
{
|
||||
if( m_layers.none() )
|
||||
updateLayers();
|
||||
|
||||
return m_layers;
|
||||
}
|
||||
|
||||
// Tag used for unconnected items.
|
||||
static const int TAG_UNCONNECTED = -1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -236,23 +180,14 @@ class EDGE
|
|||
{
|
||||
public:
|
||||
/// Constructor
|
||||
EDGE() : m_weight( 0 ), m_isLeadingEdge( false )
|
||||
EDGE() : m_isLeadingEdge( false )
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructor
|
||||
virtual ~EDGE()
|
||||
{
|
||||
}
|
||||
|
||||
/// Returns tag, common identifier for connected nodes
|
||||
inline int GetTag() const
|
||||
{
|
||||
int tag = GetSourceNode()->GetTag();
|
||||
if( tag >= 0 )
|
||||
return tag;
|
||||
|
||||
return GetTargetNode()->GetTag();
|
||||
}
|
||||
|
||||
/// Sets the source node
|
||||
|
@ -288,6 +223,9 @@ public:
|
|||
/// Returns the twin edge
|
||||
inline EDGE_PTR GetTwinEdge() const
|
||||
{
|
||||
if( m_twinEdge.expired() )
|
||||
return nullptr;
|
||||
|
||||
return m_twinEdge.lock();
|
||||
}
|
||||
|
||||
|
@ -299,6 +237,7 @@ public:
|
|||
/// Returns the next edge in face
|
||||
inline const EDGE_PTR& GetNextEdgeInFace() const
|
||||
{
|
||||
assert ( m_nextEdgeInFace );
|
||||
return m_nextEdgeInFace;
|
||||
}
|
||||
|
||||
|
@ -314,16 +253,6 @@ public:
|
|||
return m_nextEdgeInFace->GetSourceNode();
|
||||
}
|
||||
|
||||
inline void SetWeight( unsigned int weight )
|
||||
{
|
||||
m_weight = weight;
|
||||
}
|
||||
|
||||
inline unsigned int GetWeight() const
|
||||
{
|
||||
return m_weight;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_sourceNode.reset();
|
||||
|
@ -340,41 +269,9 @@ protected:
|
|||
NODE_PTR m_sourceNode;
|
||||
EDGE_WEAK_PTR m_twinEdge;
|
||||
EDGE_PTR m_nextEdgeInFace;
|
||||
unsigned int m_weight;
|
||||
bool m_isLeadingEdge;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class EDGE_MST
|
||||
* \brief \b Specialization of %EDGE class to be used for Minimum Spanning Tree algorithm.
|
||||
*/
|
||||
class EDGE_MST : public EDGE
|
||||
{
|
||||
private:
|
||||
NODE_PTR m_target;
|
||||
|
||||
public:
|
||||
EDGE_MST( const NODE_PTR& aSource, const NODE_PTR& aTarget, unsigned int aWeight = 0 ) :
|
||||
m_target( aTarget )
|
||||
{
|
||||
m_sourceNode = aSource;
|
||||
m_weight = aWeight;
|
||||
}
|
||||
|
||||
/// @copydoc Edge::setSourceNode()
|
||||
virtual const NODE_PTR& GetTargetNode() const override
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
private:
|
||||
EDGE_MST( const EDGE& aEdge )
|
||||
{
|
||||
assert( false );
|
||||
}
|
||||
};
|
||||
|
||||
class DART; // Forward declaration (class in this namespace)
|
||||
|
||||
/**
|
||||
|
@ -500,7 +397,7 @@ public:
|
|||
}
|
||||
|
||||
/// Returns a list of half-edges (one half-edge for each arc)
|
||||
std::list<EDGE_PTR>* GetEdges( bool aSkipBoundaryEdges = false ) const;
|
||||
void GetEdges( std::list<EDGE_PTR>& aEdges, bool aSkipBoundaryEdges = false ) const;
|
||||
|
||||
#ifdef TTL_USE_NODE_FLAG
|
||||
/// Sets flag in all the nodes
|
||||
|
|
|
@ -566,7 +566,7 @@ public:
|
|||
* search connections between tracks and pads and propagate pad net codes to the track
|
||||
* segments.
|
||||
*/
|
||||
void RecalculateAllTracksNetcode();
|
||||
void ComputeLegacyConnections ();
|
||||
|
||||
/* Functions relative to Undo/redo commands:
|
||||
*/
|
||||
|
|
|
@ -220,6 +220,8 @@ set( PCBNEW_CLASS_SRCS
|
|||
class_pcb_layer_box_selector.cpp
|
||||
clean.cpp
|
||||
connect.cpp
|
||||
connectivity.cpp
|
||||
connectivity_algo.cpp
|
||||
controle.cpp
|
||||
dimension.cpp
|
||||
cross-probing.cpp
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <view/view.h>
|
||||
#include <board_commit.h>
|
||||
#include <tools/pcb_tool.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include <functional>
|
||||
using namespace std::placeholders;
|
||||
|
@ -60,7 +61,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
|
|||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
BOARD* board = (BOARD*) m_toolMgr->GetModel();
|
||||
PCB_BASE_FRAME* frame = (PCB_BASE_FRAME*) m_toolMgr->GetEditFrame();
|
||||
RN_DATA* ratsnest = board->GetRatsnest();
|
||||
auto connectivity = board->GetConnectivity();
|
||||
std::set<EDA_ITEM*> savedModules;
|
||||
|
||||
if( Empty() )
|
||||
|
@ -262,7 +263,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
|
|||
}
|
||||
|
||||
view->Update ( boardItem );
|
||||
ratsnest->Update( boardItem );
|
||||
connectivity->Update( boardItem );
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -278,7 +279,7 @@ void BOARD_COMMIT::Push( const wxString& aMessage, bool aCreateUndoEntry )
|
|||
if( TOOL_MANAGER* toolMgr = frame->GetToolManager() )
|
||||
toolMgr->PostEvent( { TC_MESSAGE, TA_MODEL_CHANGE, AS_GLOBAL } );
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
frame->OnModify();
|
||||
frame->UpdateMsgPanel();
|
||||
|
||||
|
@ -307,7 +308,7 @@ void BOARD_COMMIT::Revert()
|
|||
PICKED_ITEMS_LIST undoList;
|
||||
KIGFX::VIEW* view = m_toolMgr->GetView();
|
||||
BOARD* board = (BOARD*) m_toolMgr->GetModel();
|
||||
RN_DATA* ratsnest = board->GetRatsnest();
|
||||
auto connectivity = board->GetConnectivity();
|
||||
|
||||
for( auto it = m_changes.rbegin(); it != m_changes.rend(); ++it )
|
||||
{
|
||||
|
@ -325,7 +326,7 @@ void BOARD_COMMIT::Revert()
|
|||
}
|
||||
|
||||
view->Remove( item );
|
||||
ratsnest->Remove( item );
|
||||
connectivity->Remove( item );
|
||||
break;
|
||||
|
||||
case CHT_REMOVE:
|
||||
|
@ -337,7 +338,7 @@ void BOARD_COMMIT::Revert()
|
|||
}
|
||||
|
||||
view->Add( item );
|
||||
ratsnest->Add( item );
|
||||
connectivity->Add( item );
|
||||
break;
|
||||
|
||||
case CHT_MODIFY:
|
||||
|
@ -349,7 +350,7 @@ void BOARD_COMMIT::Revert()
|
|||
}
|
||||
|
||||
view->Remove( item );
|
||||
ratsnest->Remove( item );
|
||||
connectivity->Remove( item );
|
||||
|
||||
item->SwapData( copy );
|
||||
|
||||
|
@ -365,7 +366,7 @@ void BOARD_COMMIT::Revert()
|
|||
}
|
||||
|
||||
view->Add( item );
|
||||
ratsnest->Add( item );
|
||||
connectivity->Add( item );
|
||||
delete copy;
|
||||
break;
|
||||
}
|
||||
|
@ -376,7 +377,7 @@ void BOARD_COMMIT::Revert()
|
|||
}
|
||||
}
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
clear();
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include <class_zone.h>
|
||||
|
||||
#include <pcb_netlist.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <reporter.h>
|
||||
|
||||
#include <board_netlist_updater.h>
|
||||
|
@ -669,7 +669,7 @@ bool BOARD_NETLIST_UPDATER::UpdateNetlist( NETLIST& aNetlist )
|
|||
{
|
||||
m_commit.Push( _( "Update netlist" ) );
|
||||
m_frame->Compile_Ratsnest( NULL, false );
|
||||
m_board->GetRatsnest()->ProcessBoard();
|
||||
m_board->GetConnectivity()->Build( m_board );
|
||||
testConnectivity( aNetlist );
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include <class_pcb_text.h>
|
||||
#include <class_mire.h>
|
||||
#include <class_dimension.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
|
||||
/* This is an odd place for this, but CvPcb won't link if it is
|
||||
|
@ -106,7 +107,8 @@ BOARD::BOARD() :
|
|||
m_designSettings.SetCustomViaDrill( m_designSettings.GetCurrentViaDrill() );
|
||||
|
||||
// Initialize ratsnest
|
||||
m_ratsnest = new RN_DATA( this );
|
||||
m_connectivity.reset( new CONNECTIVITY_DATA() );
|
||||
m_connectivity->Build( this );
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,8 +120,6 @@ BOARD::~BOARD()
|
|||
Delete( area_to_remove );
|
||||
}
|
||||
|
||||
delete m_ratsnest;
|
||||
|
||||
m_FullRatsnest.clear();
|
||||
m_LocalRatsnest.clear();
|
||||
|
||||
|
@ -942,7 +942,7 @@ void BOARD::Add( BOARD_ITEM* aBoardItem, ADD_MODE aMode )
|
|||
}
|
||||
|
||||
aBoardItem->SetParent( this );
|
||||
m_ratsnest->Add( aBoardItem );
|
||||
m_connectivity->Add( aBoardItem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1011,7 +1011,7 @@ void BOARD::Remove( BOARD_ITEM* aBoardItem )
|
|||
wxFAIL_MSG( wxT( "BOARD::Remove() needs more ::Type() support" ) );
|
||||
}
|
||||
|
||||
m_ratsnest->Remove( aBoardItem );
|
||||
m_connectivity->Remove( aBoardItem );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2895,3 +2895,8 @@ bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
|||
return success;
|
||||
|
||||
}
|
||||
|
||||
/*RN_DATA* BOARD::GetRatsnest() const
|
||||
{
|
||||
return m_connectivity->GetRatsnest();
|
||||
}*/
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
#include <pcb_plot_params.h>
|
||||
#include <board_item_container.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class PCB_BASE_FRAME;
|
||||
class PCB_EDIT_FRAME;
|
||||
|
@ -60,7 +63,7 @@ class NETLIST;
|
|||
class REPORTER;
|
||||
class RN_DATA;
|
||||
class SHAPE_POLY_SET;
|
||||
|
||||
class CONNECTIVITY_DATA;
|
||||
|
||||
/**
|
||||
* Enum LAYER_T
|
||||
|
@ -187,7 +190,7 @@ private:
|
|||
int m_fileFormatVersionAtLoad; ///< the version loaded from the file
|
||||
|
||||
NETINFO_LIST m_NetInfo; ///< net info list (name, design constraints ..
|
||||
RN_DATA* m_ratsnest;
|
||||
std::shared_ptr<CONNECTIVITY_DATA> m_connectivity;
|
||||
|
||||
BOARD_DESIGN_SETTINGS m_designSettings;
|
||||
ZONE_SETTINGS m_zoneSettings;
|
||||
|
@ -291,13 +294,14 @@ public:
|
|||
BOARD_ITEM* Duplicate( const BOARD_ITEM* aItem, bool aAddToBoard = false );
|
||||
|
||||
/**
|
||||
* Function GetRatsnest()
|
||||
* Function GetConnectivity()
|
||||
* returns list of missing connections between components/tracks.
|
||||
* @return RATSNEST* is an object that contains informations about missing connections.
|
||||
*/
|
||||
RN_DATA* GetRatsnest() const
|
||||
|
||||
std::shared_ptr<CONNECTIVITY_DATA> GetConnectivity() const
|
||||
{
|
||||
return m_ratsnest;
|
||||
return m_connectivity;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include <class_board.h>
|
||||
#include <class_board_item.h>
|
||||
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
BOARD_CONNECTED_ITEM::BOARD_CONNECTED_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) :
|
||||
BOARD_ITEM( aParent, idtype ), m_netinfo( &NETINFO_LIST::ORPHANED_ITEM ),
|
||||
|
@ -50,11 +50,11 @@ bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
|
|||
// set the m_netinfo to the dummy NETINFO_LIST::ORPHANED
|
||||
|
||||
BOARD* board = GetBoard();
|
||||
RN_DATA* ratsnest = board ? board->GetRatsnest() : NULL;
|
||||
bool addRatsnest = false;
|
||||
//auto connectivity = board ? board->GetConnectivity() : nullptr;
|
||||
//bool addRatsnest = false;
|
||||
|
||||
if( ratsnest )
|
||||
addRatsnest = ratsnest->Remove( this );
|
||||
//if( connectivity )
|
||||
//addRatsnest = connectivity->Remove( this );
|
||||
|
||||
if( ( aNetCode >= 0 ) && board )
|
||||
m_netinfo = board->FindNet( aNetCode );
|
||||
|
@ -65,8 +65,8 @@ bool BOARD_CONNECTED_ITEM::SetNetCode( int aNetCode, bool aNoAssert )
|
|||
assert( m_netinfo );
|
||||
|
||||
// Add only if it was previously added to the ratsnest
|
||||
if( addRatsnest )
|
||||
ratsnest->Add( this );
|
||||
//if( addRatsnest )
|
||||
// connectivity->Add( this );
|
||||
|
||||
return ( m_netinfo != NULL );
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
class NETCLASS;
|
||||
class TRACK;
|
||||
class D_PAD;
|
||||
class CN_BOARD_ITEM_DATA;
|
||||
|
||||
/**
|
||||
* Class BOARD_CONNECTED_ITEM
|
||||
|
@ -50,6 +51,8 @@ class BOARD_CONNECTED_ITEM : public BOARD_ITEM
|
|||
friend class CONNECTIONS;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
// These 2 members are used for temporary storage during connections calculations:
|
||||
std::vector<TRACK*> m_TracksConnected; // list of other tracks connected to me
|
||||
std::vector<D_PAD*> m_PadsConnected; // list of other pads connected to me
|
||||
|
|
|
@ -637,6 +637,12 @@ public:
|
|||
m_FillSegmList.insert( m_FillSegmList.end(), aSegments.begin(), aSegments.end() );
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET& RawPolysList()
|
||||
{
|
||||
return m_RawPolysList;
|
||||
}
|
||||
|
||||
|
||||
wxString GetSelectMenuText() const override;
|
||||
|
||||
BITMAP_DEF GetMenuImage() const override;
|
||||
|
@ -781,6 +787,7 @@ private:
|
|||
* described by m_Poly can have many filled areas
|
||||
*/
|
||||
SHAPE_POLY_SET m_FilledPolysList;
|
||||
SHAPE_POLY_SET m_RawPolysList;
|
||||
|
||||
HATCH_STYLE m_hatchStyle; // hatch style, see enum above
|
||||
int m_hatchPitch; // for DIAGONAL_EDGE, distance between 2 hatch lines
|
||||
|
|
|
@ -39,9 +39,13 @@
|
|||
// Helper classes to handle connection points
|
||||
#include <connect.h>
|
||||
|
||||
const bool g_UseLegacyConnectionAlgo = false;
|
||||
|
||||
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb );
|
||||
extern void Merge_SubNets_Connected_By_CopperAreas( BOARD* aPcb, int aNetcode );
|
||||
|
||||
|
||||
|
||||
// Local functions
|
||||
static void RebuildTrackChain( BOARD* pcb );
|
||||
|
||||
|
@ -853,13 +857,9 @@ void PCB_BASE_FRAME::TestNetConnection( wxDC* aDC, int aNetCode )
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/* search connections between tracks and pads and propagate pad net codes to the track
|
||||
* segments.
|
||||
* Pads netcodes are assumed to be up to date.
|
||||
*/
|
||||
void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
|
||||
void PCB_BASE_FRAME::ComputeLegacyConnections()
|
||||
{
|
||||
|
||||
// Build the net info list
|
||||
GetBoard()->BuildListOfNets();
|
||||
|
||||
|
@ -872,7 +872,6 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
|
|||
t->end = NULL;
|
||||
t->SetState( BUSY | IN_EDIT | BEGIN_ONPAD | END_ONPAD, false );
|
||||
t->SetZoneSubNet( 0 );
|
||||
t->SetNetCode( NETINFO_LIST::UNCONNECTED );
|
||||
}
|
||||
|
||||
// If no pad, reset pointers and netcode, and do nothing else
|
||||
|
@ -886,72 +885,12 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
|
|||
// First pass: build connections between track segments and pads.
|
||||
connections.SearchTracksConnectedToPads();
|
||||
|
||||
// For tracks connected to at least one pad,
|
||||
// set the track net code to the pad netcode
|
||||
for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() )
|
||||
{
|
||||
if( t->m_PadsConnected.size() )
|
||||
t->SetNetCode( t->m_PadsConnected[0]->GetNetCode() );
|
||||
}
|
||||
|
||||
// Pass 2: build connections between track ends
|
||||
for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() )
|
||||
{
|
||||
connections.SearchConnectedTracks( t );
|
||||
connections.GetConnectedTracks( t );
|
||||
}
|
||||
|
||||
// Propagate net codes from a segment to other connected segments
|
||||
bool new_pass_request = true; // set to true if a track has its netcode changed from 0
|
||||
// to a known netcode to re-evaluate netcodes
|
||||
// of connected items
|
||||
while( new_pass_request )
|
||||
{
|
||||
new_pass_request = false;
|
||||
|
||||
for( TRACK* t = m_Pcb->m_Track; t; t = t->Next() )
|
||||
{
|
||||
int netcode = t->GetNetCode();
|
||||
|
||||
if( netcode == 0 )
|
||||
{
|
||||
// try to find a connected item having a netcode
|
||||
for( unsigned kk = 0; kk < t->m_TracksConnected.size(); kk++ )
|
||||
{
|
||||
int altnetcode = t->m_TracksConnected[kk]->GetNetCode();
|
||||
if( altnetcode )
|
||||
{
|
||||
new_pass_request = true;
|
||||
netcode = altnetcode;
|
||||
t->SetNetCode(netcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( netcode ) // this track has a netcode
|
||||
{
|
||||
// propagate this netcode to connected tracks having no netcode
|
||||
for( unsigned kk = 0; kk < t->m_TracksConnected.size(); kk++ )
|
||||
{
|
||||
int altnetcode = t->m_TracksConnected[kk]->GetNetCode();
|
||||
if( altnetcode == 0 )
|
||||
{
|
||||
t->m_TracksConnected[kk]->SetNetCode(netcode);
|
||||
new_pass_request = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( IsGalCanvasActive() )
|
||||
{
|
||||
/// @todo LEGACY tracks might have changed their nets, so we need to refresh labels in GAL
|
||||
for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
|
||||
GetGalCanvas()->GetView()->Update( track );
|
||||
}
|
||||
|
||||
// Sort the track list by net codes:
|
||||
RebuildTrackChain( m_Pcb );
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -33,7 +33,7 @@
|
|||
#include <confirm.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <macros.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_track.h>
|
||||
|
@ -123,7 +123,7 @@ TRACK* PCB_EDIT_FRAME::Delete_Segment( wxDC* DC, TRACK* aTrack )
|
|||
// Remove the segment from list, but do not delete it (it will be stored i n undo list)
|
||||
GetBoard()->Remove( aTrack );
|
||||
|
||||
GetBoard()->GetRatsnest()->Remove( aTrack );
|
||||
GetBoard()->GetConnectivity()->Remove( aTrack );
|
||||
|
||||
// redraw the area where the track was
|
||||
m_canvas->RefreshDrawingRect( aTrack->GetBoundingBox() );
|
||||
|
@ -173,7 +173,7 @@ void PCB_EDIT_FRAME::Delete_net( wxDC* DC, TRACK* aTrack )
|
|||
if( segm->GetNetCode() != netcode )
|
||||
break;
|
||||
|
||||
GetBoard()->GetRatsnest()->Remove( segm );
|
||||
GetBoard()->GetConnectivity()->Remove( segm );
|
||||
GetBoard()->m_Track.Remove( segm );
|
||||
|
||||
// redraw the area where the track was
|
||||
|
@ -219,7 +219,7 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm )
|
|||
<< TO_UTF8( TRACK::ShowState( tracksegment->GetStatus() ) ) \
|
||||
<< std::endl; )
|
||||
|
||||
GetBoard()->GetRatsnest()->Remove( tracksegment );
|
||||
GetBoard()->GetConnectivity()->Remove( tracksegment );
|
||||
GetBoard()->m_Track.Remove( tracksegment );
|
||||
|
||||
// redraw the area where the track was
|
||||
|
|
|
@ -846,7 +846,6 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">bMiddleRightBoxSizer</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="0">
|
||||
|
@ -1580,7 +1579,6 @@
|
|||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer2PAN</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="parent">1</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="0">
|
||||
|
@ -1849,6 +1847,108 @@
|
|||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">1</property>
|
||||
<object class="wxStaticBoxSizer" expanded="1">
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Advanced/Developer</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">sbSizer4</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">none</property>
|
||||
<event name="OnUpdateUI"></event>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxALL</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxCheckBox" expanded="1">
|
||||
<property name="BottomDockable">1</property>
|
||||
<property name="LeftDockable">1</property>
|
||||
<property name="RightDockable">1</property>
|
||||
<property name="TopDockable">1</property>
|
||||
<property name="aui_layer"></property>
|
||||
<property name="aui_name"></property>
|
||||
<property name="aui_position"></property>
|
||||
<property name="aui_row"></property>
|
||||
<property name="best_size"></property>
|
||||
<property name="bg"></property>
|
||||
<property name="caption"></property>
|
||||
<property name="caption_visible">1</property>
|
||||
<property name="center_pane">0</property>
|
||||
<property name="checked">0</property>
|
||||
<property name="close_button">1</property>
|
||||
<property name="context_help"></property>
|
||||
<property name="context_menu">1</property>
|
||||
<property name="default_pane">0</property>
|
||||
<property name="dock">Dock</property>
|
||||
<property name="dock_fixed">0</property>
|
||||
<property name="docking">Left</property>
|
||||
<property name="enabled">1</property>
|
||||
<property name="fg"></property>
|
||||
<property name="floatable">1</property>
|
||||
<property name="font"></property>
|
||||
<property name="gripper">0</property>
|
||||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="label">Use legacy connectivity algorithm</property>
|
||||
<property name="max_size"></property>
|
||||
<property name="maximize_button">0</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="min_size"></property>
|
||||
<property name="minimize_button">0</property>
|
||||
<property name="minimum_size"></property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_cbUseLegacyConnectivityAlgo</property>
|
||||
<property name="pane_border">1</property>
|
||||
<property name="pane_position"></property>
|
||||
<property name="pane_size"></property>
|
||||
<property name="permission">protected</property>
|
||||
<property name="pin_button">1</property>
|
||||
<property name="pos"></property>
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="validator_data_type"></property>
|
||||
<property name="validator_style">wxFILTER_NONE</property>
|
||||
<property name="validator_type">wxDefaultValidator</property>
|
||||
<property name="validator_variable"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnCheckBox"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
|
|
@ -160,7 +160,7 @@ void DIALOG_GLOBAL_DELETION::AcceptPcbDelete()
|
|||
|
||||
masque_layer &= layers_filter;
|
||||
|
||||
for( item = pcb->m_Drawings; item; item = item->Next() )
|
||||
for( item = pcb->DrawingsList(); item; item = item->Next() )
|
||||
{
|
||||
KICAD_T type = item->Type();
|
||||
LAYER_NUM layer = item->GetLayer();
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
#include <class_board_design_settings.h>
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <wildcards_and_files_ext.h>
|
||||
|
||||
#include <dialog_netlist.h>
|
||||
|
@ -330,9 +330,9 @@ void DIALOG_NETLIST::OnTestFootprintsClick( wxCommandEvent& event )
|
|||
void DIALOG_NETLIST::OnCompileRatsnestClick( wxCommandEvent& event )
|
||||
{
|
||||
// Rebuild the board connectivity:
|
||||
if( m_parent->IsGalCanvasActive() )
|
||||
m_parent->GetBoard()->GetRatsnest()->ProcessBoard();
|
||||
|
||||
auto board = m_parent->GetBoard();
|
||||
//board->GetConnectivity()->Build( board );
|
||||
board->GetConnectivity()->PropagateNets();
|
||||
m_parent->Compile_Ratsnest( m_dc, true );
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <view/view.h>
|
||||
#include <geometry/seg.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
|
@ -205,7 +206,7 @@ void DRC::RunTests( wxTextCtrl* aMessages )
|
|||
}
|
||||
|
||||
m_pcbEditorFrame->Compile_Ratsnest( NULL, true );
|
||||
m_pcb->GetRatsnest()->ProcessBoard();
|
||||
//m_pcb->GetRatsnest()->ProcessBoard();
|
||||
}
|
||||
|
||||
// someone should have cleared the two lists before calling this.
|
||||
|
@ -558,6 +559,25 @@ void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar )
|
|||
|
||||
void DRC::testUnconnected()
|
||||
{
|
||||
std::vector<CN_DISJOINT_NET_ENTRY> report;
|
||||
|
||||
auto connectivity = m_pcb->GetConnectivity();
|
||||
|
||||
connectivity->CheckConnectivity( report );
|
||||
|
||||
printf("Connectivity: %d unconnected\n", report.size());
|
||||
|
||||
for( auto ent : report )
|
||||
{
|
||||
/* DRC_ITEM* uncItem = new DRC_ITEM( DRCE_UNCONNECTED_PADS,
|
||||
msg,
|
||||
padEnd->GetSelectMenuText(),
|
||||
padStart->GetPosition(), padEnd->GetPosition() );*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if( (m_pcb->m_Status_Pcb & LISTE_RATSNEST_ITEM_OK) == 0 )
|
||||
{
|
||||
wxClientDC dc( m_pcbEditorFrame->GetCanvas() );
|
||||
|
@ -588,6 +608,8 @@ void DRC::testUnconnected()
|
|||
|
||||
m_unconnected.push_back( uncItem );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -584,7 +584,7 @@ bool PCB_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
|
|||
{
|
||||
wxBusyCursor dummy; // Displays an Hourglass while building connectivity
|
||||
Compile_Ratsnest( NULL, true );
|
||||
GetBoard()->GetRatsnest()->ProcessBoard();
|
||||
//GetBoard()->GetRatsnest()->ProcessBoard();
|
||||
}
|
||||
|
||||
// Update info shown by the horizontal toolbars
|
||||
|
|
|
@ -303,7 +303,7 @@ MODULE* PCB_BASE_FRAME::LoadModuleFromLibrary( const wxString& aLibrary,
|
|||
// (Can happen if the lib is an archive built from a board)
|
||||
Rotate_Module( NULL, module, 0, false );
|
||||
|
||||
RecalculateAllTracksNetcode();
|
||||
//RecalculateAllTracksNetcode();
|
||||
|
||||
if( aDC )
|
||||
module->Draw( m_canvas, aDC, GR_OR );
|
||||
|
|
|
@ -170,7 +170,7 @@ void PCB_EDIT_FRAME::ReadPcbNetlist( const wxString& aNetlistFileName,
|
|||
|
||||
// Rebuild the board connectivity:
|
||||
Compile_Ratsnest( NULL, true );
|
||||
board->GetRatsnest()->ProcessBoard();
|
||||
//board->GetRatsnest()->ProcessBoard();
|
||||
|
||||
SetMsgPanel( board );
|
||||
m_canvas->Refresh();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <worksheet_viewitem.h>
|
||||
#include <ratsnest_viewitem.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include <class_colors_design_settings.h>
|
||||
#include <class_board.h>
|
||||
|
@ -154,7 +155,7 @@ void PCB_DRAW_PANEL_GAL::DisplayBoard( const BOARD* aBoard )
|
|||
m_view->Add( zone );
|
||||
|
||||
// Ratsnest
|
||||
m_ratsnest.reset( new KIGFX::RATSNEST_VIEWITEM( aBoard->GetRatsnest() ) );
|
||||
m_ratsnest.reset( new KIGFX::RATSNEST_VIEWITEM( aBoard->GetConnectivity() ) );
|
||||
m_view->Add( m_ratsnest.get() );
|
||||
|
||||
// Display settings
|
||||
|
@ -334,7 +335,7 @@ void PCB_DRAW_PANEL_GAL::GetMsgPanelInfo( std::vector<MSG_PANEL_ITEM>& aList )
|
|||
txt.Printf( wxT( "%d" ), board->GetNetCount() );
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Nets" ), txt, RED ) );
|
||||
|
||||
txt.Printf( wxT( "%d" ), board->GetRatsnest()->GetUnconnectedCount() );
|
||||
txt.Printf( wxT( "%d" ), board->GetConnectivity()->GetUnconnectedCount() );
|
||||
aList.push_back( MSG_PANEL_ITEM( _( "Unconnected" ), txt, BLUE ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <worksheet_viewitem.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <ratsnest_viewitem.h>
|
||||
|
||||
#include <tool/tool_manager.h>
|
||||
|
@ -509,7 +509,7 @@ void PCB_EDIT_FRAME::SetBoard( BOARD* aBoard )
|
|||
|
||||
if( IsGalCanvasActive() )
|
||||
{
|
||||
aBoard->GetRatsnest()->ProcessBoard();
|
||||
aBoard->GetConnectivity()->Build ( aBoard );
|
||||
|
||||
// reload the worksheet
|
||||
SetPageSettings( aBoard->GetPageSettings() );
|
||||
|
|
|
@ -170,7 +170,7 @@ void PCB_BASE_FRAME::Compile_Ratsnest( wxDC* aDC, bool aDisplayStatus )
|
|||
ClearMsgPanel();
|
||||
|
||||
// Rebuild the full pads and net info list
|
||||
RecalculateAllTracksNetcode();
|
||||
ComputeLegacyConnections();
|
||||
|
||||
if( aDisplayStatus )
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -30,50 +30,28 @@
|
|||
#ifndef RATSNEST_DATA_H
|
||||
#define RATSNEST_DATA_H
|
||||
|
||||
#include <ttl/halfedge/hetriang.h>
|
||||
#include <ttl/halfedge/hetraits.h>
|
||||
|
||||
#include <core/typeinfo.h>
|
||||
#include <math/box2.h>
|
||||
|
||||
#include <deque>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ttl/halfedge/hetriang.h>
|
||||
#include <ttl/halfedge/hetraits.h>
|
||||
|
||||
#include <connectivity_algo.h>
|
||||
|
||||
class BOARD;
|
||||
class BOARD_ITEM;
|
||||
class BOARD_CONNECTED_ITEM;
|
||||
class MODULE;
|
||||
class D_PAD;
|
||||
class VIA;
|
||||
class TRACK;
|
||||
class ZONE_CONTAINER;
|
||||
class SHAPE_POLY_SET;
|
||||
|
||||
///> Types of items that are handled by the class
|
||||
enum RN_ITEM_TYPE
|
||||
{
|
||||
RN_PADS = 0x01,
|
||||
RN_VIAS = 0x02,
|
||||
RN_TRACKS = 0x04,
|
||||
RN_ZONES = 0x08,
|
||||
RN_ALL = 0xFF
|
||||
};
|
||||
|
||||
// Preserve KiCad coding style policy
|
||||
typedef hed::NODE RN_NODE;
|
||||
typedef hed::NODE_PTR RN_NODE_PTR;
|
||||
typedef hed::EDGE RN_EDGE;
|
||||
typedef hed::EDGE_PTR RN_EDGE_PTR;
|
||||
typedef hed::EDGE_MST RN_EDGE_MST;
|
||||
typedef hed::TRIANGULATION TRIANGULATOR;
|
||||
typedef std::shared_ptr<hed::EDGE_MST> RN_EDGE_MST_PTR;
|
||||
|
||||
bool operator==( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond );
|
||||
bool operator!=( const RN_NODE_PTR& aFirst, const RN_NODE_PTR& aSecond );
|
||||
class CN_CLUSTER;
|
||||
class CN_CONNECTIVITY_ALGO;
|
||||
|
||||
struct RN_NODE_OR_FILTER;
|
||||
struct RN_NODE_AND_FILTER;
|
||||
|
||||
#if 0
|
||||
///> General interface for filtering out nodes in search functions.
|
||||
struct RN_NODE_FILTER : public std::unary_function<const RN_NODE_PTR&, bool>
|
||||
{
|
||||
|
@ -96,7 +74,7 @@ struct LINE_TARGET : public RN_NODE_FILTER
|
|||
{
|
||||
bool operator()( const RN_NODE_PTR& aNode ) const override
|
||||
{
|
||||
return !aNode->GetNoLine();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -109,7 +87,7 @@ struct LINE_TARGET_SAME_TAG : public RN_NODE_FILTER
|
|||
|
||||
bool operator()( const RN_NODE_PTR& aNode ) const override
|
||||
{
|
||||
return !aNode->GetNoLine() && aNode->GetTag() == m_tag;
|
||||
return aNode->GetTag() == m_tag;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -124,7 +102,7 @@ struct LINE_TARGET_DIFF_TAG : public RN_NODE_FILTER
|
|||
|
||||
bool operator()( const RN_NODE_PTR& aNode ) const override
|
||||
{
|
||||
return !aNode->GetNoLine() && aNode->GetTag() == m_tag;
|
||||
return aNode->GetTag() != m_tag;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -163,168 +141,26 @@ struct RN_NODE_OR_FILTER : public RN_NODE_FILTER
|
|||
const RN_NODE_FILTER& m_filter2;
|
||||
};
|
||||
|
||||
|
||||
///> Functor comparing if two nodes are equal by their coordinates. It is required to make set of
|
||||
///> shared pointers work properly.
|
||||
struct RN_NODE_COMPARE : std::binary_function<RN_NODE_PTR, RN_NODE_PTR, bool>
|
||||
struct RN_NODE_COMPARE : std::binary_function<CN_ANCHOR_PTR, CN_ANCHOR_PTR, bool>
|
||||
{
|
||||
bool operator()( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2 ) const
|
||||
bool operator()( const CN_ANCHOR_PTR& aNode1, const CN_ANCHOR_PTR& aNode2 ) const
|
||||
{
|
||||
return aNode1 == aNode2;
|
||||
if ( aNode1->GetY() < aNode2->GetY() )
|
||||
return true;
|
||||
else if ( aNode1->GetY() == aNode2->GetY() )
|
||||
{
|
||||
if ( aNode1->GetX() == aNode2->GetX() )
|
||||
return aNode1->GetCluster() < aNode2->GetCluster();
|
||||
else
|
||||
return aNode1->GetX() < aNode2->GetX();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
///> Functor calculating hash for a given node. It is required to make set of shared pointers
|
||||
///> work properly.
|
||||
struct RN_NODE_HASH : std::unary_function<RN_NODE_PTR, std::size_t>
|
||||
{
|
||||
std::size_t operator()( const RN_NODE_PTR& aNode ) const
|
||||
{
|
||||
std::size_t hash = 2166136261u;
|
||||
|
||||
hash ^= aNode->GetX();
|
||||
hash *= 16777619;
|
||||
hash ^= aNode->GetY();
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class RN_LINKS
|
||||
* Manages data describing nodes and connections for a given net.
|
||||
*/
|
||||
class RN_LINKS
|
||||
{
|
||||
public:
|
||||
// Helper typedefs
|
||||
typedef std::unordered_set<RN_NODE_PTR, RN_NODE_HASH, RN_NODE_COMPARE> RN_NODE_SET;
|
||||
typedef std::list<RN_EDGE_PTR> RN_EDGE_LIST;
|
||||
|
||||
/**
|
||||
* Function AddNode()
|
||||
* Adds a node with given coordinates and returns pointer to the newly added node. If the node
|
||||
* existed before, only appropriate pointer is returned.
|
||||
* @param aX is the x coordinate of a node.
|
||||
* @param aY is the y coordinate of a node.
|
||||
* @return Pointer to the node with given coordinates.
|
||||
*/
|
||||
const RN_NODE_PTR& AddNode( int aX, int aY );
|
||||
|
||||
/**
|
||||
* Function RemoveNode()
|
||||
* Removes a node described by a given node pointer.
|
||||
* @param aNode is a pointer to node to be removed.
|
||||
* @return True if node was removed, false if there were other references, so it was kept.
|
||||
*/
|
||||
bool RemoveNode( const RN_NODE_PTR& aNode );
|
||||
|
||||
/**
|
||||
* Function GetNodes()
|
||||
* Returns the set of currently used nodes.
|
||||
* @return The set of currently used nodes.
|
||||
*/
|
||||
const RN_NODE_SET& GetNodes() const
|
||||
{
|
||||
return m_nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function AddConnection()
|
||||
* Adds a connection between two nodes and of given distance. Edges with distance equal 0 are
|
||||
* considered to be existing connections. Distance different than 0 means that the connection
|
||||
* is missing.
|
||||
* @param aNode1 is the origin node of a new connection.
|
||||
* @param aNode2 is the end node of a new connection.
|
||||
* @param aDistance is the distance of the connection (0 means that nodes are actually
|
||||
* connected, >0 means a missing connection).
|
||||
*/
|
||||
RN_EDGE_MST_PTR AddConnection( const RN_NODE_PTR& aNode1, const RN_NODE_PTR& aNode2,
|
||||
unsigned int aDistance = 0 );
|
||||
|
||||
/**
|
||||
* Function RemoveConnection()
|
||||
* Removes a connection described by a given edge pointer.
|
||||
* @param aEdge is a pointer to edge to be removed.
|
||||
*/
|
||||
void RemoveConnection( const RN_EDGE_PTR& aEdge )
|
||||
{
|
||||
m_edges.remove( aEdge );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetConnections()
|
||||
* Returns the list of edges that currently connect nodes.
|
||||
* @return the list of edges that currently connect nodes.
|
||||
*/
|
||||
const RN_EDGE_LIST& GetConnections() const
|
||||
{
|
||||
return m_edges;
|
||||
}
|
||||
|
||||
protected:
|
||||
///> Set of nodes that are expected to be connected together (vias, tracks, pads).
|
||||
RN_NODE_SET m_nodes;
|
||||
|
||||
///> List of edges that currently connect nodes.
|
||||
RN_EDGE_LIST m_edges;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class RN_POLY
|
||||
* Describes a single subpolygon (ZONE_CONTAINER is supposed to contain one or more of those) and
|
||||
* performs fast point-inside-polygon test.
|
||||
*/
|
||||
class RN_POLY
|
||||
{
|
||||
public:
|
||||
RN_POLY( const SHAPE_POLY_SET* aParent,
|
||||
int aSubpolygonIndex,
|
||||
RN_LINKS& aConnections, const BOX2I& aBBox );
|
||||
|
||||
/**
|
||||
* Function GetNode()
|
||||
* Returns node representing a polygon (it has the same coordinates as the first point of its
|
||||
* bounding polyline.
|
||||
*/
|
||||
inline const RN_NODE_PTR& GetNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
inline RN_NODE_PTR& GetNode()
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function HitTest()
|
||||
* Tests if selected node is located within polygon boundaries.
|
||||
* @param aNode is a node to be checked.
|
||||
* @return True is the node is located within polygon boundaries.
|
||||
*/
|
||||
bool HitTest( const RN_NODE_PTR& aNode ) const;
|
||||
|
||||
private:
|
||||
|
||||
///> Index of the outline in the parent polygon set
|
||||
int m_subpolygonIndex;
|
||||
|
||||
///> Bounding box of the polygon.
|
||||
BOX2I m_bbox;
|
||||
|
||||
///> Polygon set containing the geometry
|
||||
const SHAPE_POLY_SET* m_parentPolyset;
|
||||
|
||||
///> Node representing a polygon (it has the same coordinates as the first point of its
|
||||
///> bounding polyline.
|
||||
RN_NODE_PTR m_node;
|
||||
|
||||
friend bool sortArea( const RN_POLY& aP1, const RN_POLY& aP2 );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Class RN_NET
|
||||
|
@ -334,8 +170,7 @@ class RN_NET
|
|||
{
|
||||
public:
|
||||
///> Default constructor.
|
||||
RN_NET() : m_dirty( true ), m_visible( true )
|
||||
{}
|
||||
RN_NET();
|
||||
|
||||
/**
|
||||
* Function SetVisible()
|
||||
|
@ -383,9 +218,9 @@ public:
|
|||
* Returns pointer to a vector of edges that makes ratsnest for a given net.
|
||||
* @return Pointer to a vector of edges that makes ratsnest for a given net.
|
||||
*/
|
||||
const std::vector<RN_EDGE_MST_PTR>* GetUnconnected() const
|
||||
const std::vector<CN_EDGE> GetUnconnected() const
|
||||
{
|
||||
return m_rnEdges.get();
|
||||
return m_rnEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -393,70 +228,12 @@ public:
|
|||
* Recomputes ratsnest for a net.
|
||||
*/
|
||||
void Update();
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Function AddItem()
|
||||
* Adds an appropriate node associated with selected pad, so it is
|
||||
* taken into account during ratsnest computations.
|
||||
* @param aPad is a pad for which node is added.
|
||||
*/
|
||||
bool AddItem( const D_PAD* aPad );
|
||||
void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster );
|
||||
|
||||
/**
|
||||
* Function AddItem()
|
||||
* Adds an appropriate node associated with selected via, so it is
|
||||
* taken into account during ratsnest computations.
|
||||
* @param aVia is a via for which node is added.
|
||||
*/
|
||||
bool AddItem( const VIA* aVia );
|
||||
|
||||
/**
|
||||
* Function AddItem()
|
||||
* Adds appropriate nodes and edges associated with selected track, so they are
|
||||
* taken into account during ratsnest computations.
|
||||
* @param aTrack is a track for which nodes and edges are added.
|
||||
*/
|
||||
bool AddItem( const TRACK* aTrack );
|
||||
|
||||
/**
|
||||
* Function AddItem()
|
||||
* Processes zone to split it into subpolygons and adds appropriate nodes for them, so they are
|
||||
* taken into account during ratsnest computations.
|
||||
* @param aZone is a zone to be processed.
|
||||
*/
|
||||
bool AddItem( const ZONE_CONTAINER* aZone );
|
||||
|
||||
/**
|
||||
* Function RemoveItem()
|
||||
* Removes all nodes and edges associated with selected pad, so they are not
|
||||
* taken into account during ratsnest computations anymore.
|
||||
* @param aPad is a pad for which nodes and edges are removed.
|
||||
*/
|
||||
bool RemoveItem( const D_PAD* aPad );
|
||||
|
||||
/**
|
||||
* Function RemoveItem()
|
||||
* Removes all nodes and edges associated with selected via, so they are not
|
||||
* taken into account during ratsnest computations anymore.
|
||||
* @param aVia is a via for which nodes and edges are removed.
|
||||
*/
|
||||
bool RemoveItem( const VIA* aVia );
|
||||
|
||||
/**
|
||||
* Function RemoveItem()
|
||||
* Removes all nodes and edges associated with selected track, so they are not
|
||||
* taken into account during ratsnest computations anymore.
|
||||
* @param aTrack is a track for which nodes and edges are removed.
|
||||
*/
|
||||
bool RemoveItem( const TRACK* aTrack );
|
||||
|
||||
/**
|
||||
* Function RemoveItem()
|
||||
* Removes all nodes and edges associated with selected zone, so they are not
|
||||
* taken into account during ratsnest computations anymore.
|
||||
* @param aZone is a zone for which nodes and edges are removed.
|
||||
*/
|
||||
bool RemoveItem( const ZONE_CONTAINER* aZone );
|
||||
unsigned int GetNodeCount() const;
|
||||
|
||||
/**
|
||||
* Function GetNodes()
|
||||
|
@ -464,7 +241,12 @@ public:
|
|||
* @param aItem is an item for which the list is generated.
|
||||
* @return List of associated nodes.
|
||||
*/
|
||||
std::list<RN_NODE_PTR> GetNodes( const BOARD_CONNECTED_ITEM* aItem ) const;
|
||||
std::list<CN_ANCHOR_PTR> GetNodes( const BOARD_CONNECTED_ITEM* aItem ) const;
|
||||
|
||||
const std::vector<CN_EDGE>& GetEdges() const
|
||||
{
|
||||
return m_rnEdges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetAllItems()
|
||||
|
@ -472,14 +254,16 @@ public:
|
|||
* @param aOutput is the list that will have items added.
|
||||
* @param aType determines the type of added items.
|
||||
*/
|
||||
void GetAllItems( std::list<BOARD_CONNECTED_ITEM*>& aOutput, RN_ITEM_TYPE aType = RN_ALL ) const;
|
||||
void GetAllItems( std::list<BOARD_CONNECTED_ITEM*>& aOutput, const KICAD_T aTypes[] ) const;
|
||||
|
||||
/**
|
||||
* Function GetClosestNode()
|
||||
* Returns a single node that lies in the shortest distance from a specific node.
|
||||
* @param aNode is the node for which the closest node is searched.
|
||||
*/
|
||||
const RN_NODE_PTR GetClosestNode( const RN_NODE_PTR& aNode ) const;
|
||||
const CN_ANCHOR_PTR GetClosestNode( const CN_ANCHOR_PTR& aNode ) const;
|
||||
|
||||
bool NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode1, CN_ANCHOR_PTR& aNode2 ) const;
|
||||
|
||||
/**
|
||||
* Function GetClosestNode()
|
||||
|
@ -488,8 +272,8 @@ public:
|
|||
* @param aNode is the node for which the closest node is searched.
|
||||
* @param aFilter is a functor that filters nodes.
|
||||
*/
|
||||
const RN_NODE_PTR GetClosestNode( const RN_NODE_PTR& aNode,
|
||||
const RN_NODE_FILTER& aFilter ) const;
|
||||
/*const CN_ANCHOR_PTR GetClosestNode( const RN_NODE_PTR& aNode,
|
||||
const RN_NODE_FILTER& aFilter ) const;*/
|
||||
|
||||
/**
|
||||
* Function GetClosestNodes()
|
||||
|
@ -499,7 +283,7 @@ public:
|
|||
* belong to the same net are returned. If asked number is greater than number of possible
|
||||
* nodes then the size of list is limited to number of possible nodes.
|
||||
*/
|
||||
std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, int aNumber = -1 ) const;
|
||||
//std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode, int aNumber = -1 ) const;
|
||||
|
||||
/**
|
||||
* Function GetClosestNodes()
|
||||
|
@ -510,291 +294,33 @@ public:
|
|||
* belong to the same net are returned. If asked number is greater than number of possible
|
||||
* nodes then the size of list is limited to number of possible nodes.
|
||||
*/
|
||||
std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode,
|
||||
const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const;
|
||||
//std::list<RN_NODE_PTR> GetClosestNodes( const RN_NODE_PTR& aNode,
|
||||
// const RN_NODE_FILTER& aFilter, int aNumber = -1 ) const;
|
||||
|
||||
/**
|
||||
* Function AddSimple()
|
||||
* Changes drawing mode for an item to simple (i.e. one ratsnest line per node).
|
||||
* @param aItem is the item that changes its drawing mode.
|
||||
*/
|
||||
void AddSimple( const BOARD_CONNECTED_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function AddBlockedNode()
|
||||
* Specifies a node as not suitable as a ratsnest line target (i.e. ratsnest lines will not
|
||||
* target the node). The status is cleared after calling ClearSimple().
|
||||
* @param aNode is the node that is not going to be used as a ratsnest line target.
|
||||
*/
|
||||
inline void AddBlockedNode( RN_NODE_PTR& aNode )
|
||||
{
|
||||
m_blockedNodes.insert( aNode );
|
||||
aNode->SetNoLine( true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetSimpleNodes()
|
||||
* Returns list of nodes for which ratsnest is drawn in simple mode (i.e. one
|
||||
* ratsnest line per node).
|
||||
* @return list of nodes for which ratsnest is drawn in simple mode.
|
||||
*/
|
||||
inline const std::unordered_set<RN_NODE_PTR>& GetSimpleNodes() const
|
||||
{
|
||||
return m_simpleNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ClearSimple()
|
||||
* Removes all nodes and edges that are used for displaying ratsnest in simple mode.
|
||||
*/
|
||||
void ClearSimple();
|
||||
|
||||
/**
|
||||
* Function GetConnectedItems()
|
||||
* Adds items that are connected together to a list.
|
||||
* @param aItem is the reference item to find other connected items.
|
||||
* @param aOutput is the list that will contain found items.
|
||||
* @param aTypes allows to filter by item types.
|
||||
*/
|
||||
void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
|
||||
std::list<BOARD_CONNECTED_ITEM*>& aOutput,
|
||||
RN_ITEM_TYPE aTypes = RN_ALL ) const;
|
||||
|
||||
protected:
|
||||
///> Validates edge, i.e. modifies source and target nodes for an edge
|
||||
///> to make sure that they are not ones with the flag set.
|
||||
void validateEdge( RN_EDGE_MST_PTR& aEdge );
|
||||
|
||||
///> Removes a link between a node and a parent,
|
||||
///> and clears linked edges if it was the last parent.
|
||||
void removeNode( RN_NODE_PTR& aNode, const BOARD_CONNECTED_ITEM* aParent );
|
||||
|
||||
///> Removes a link between an edge and a parent,
|
||||
///> and clears its node data if it was the last parent.
|
||||
void removeEdge( RN_EDGE_MST_PTR& aEdge, const BOARD_CONNECTED_ITEM* aParent );
|
||||
|
||||
///> Removes all ratsnest edges for a given node.
|
||||
void clearNode( const RN_NODE_PTR& aNode );
|
||||
|
||||
///> Adds appropriate edges for nodes that are connected by zones.
|
||||
void processZones();
|
||||
|
||||
///> Adds additional edges to account for connections made by items located in pads areas.
|
||||
void processPads();
|
||||
|
||||
///> Recomputes ratsnset from scratch.
|
||||
void compute();
|
||||
|
||||
////> Stores information about connections for a given net.
|
||||
RN_LINKS m_links;
|
||||
///> Vector of nodes
|
||||
std::vector<CN_ANCHOR_PTR> m_nodes;
|
||||
|
||||
///> Vector of edges that make pre-defined connections
|
||||
std::vector<CN_EDGE> m_boardEdges;
|
||||
|
||||
///> Vector of edges that makes ratsnest for a given net.
|
||||
std::shared_ptr< std::vector<RN_EDGE_MST_PTR> > m_rnEdges;
|
||||
|
||||
///> List of nodes which will not be used as ratsnest target nodes.
|
||||
std::unordered_set<RN_NODE_PTR> m_blockedNodes;
|
||||
|
||||
///> Nodes to be displayed using the simplified ratsnest algorithm.
|
||||
std::unordered_set<RN_NODE_PTR> m_simpleNodes;
|
||||
std::vector<CN_EDGE> m_rnEdges;
|
||||
|
||||
///> Flag indicating necessity of recalculation of ratsnest for a net.
|
||||
bool m_dirty;
|
||||
|
||||
///> Structure to hold ratsnest data for ZONE_CONTAINER objects.
|
||||
typedef struct
|
||||
{
|
||||
///> Subpolygons belonging to a zone
|
||||
std::deque<RN_POLY> m_Polygons;
|
||||
|
||||
///> Connections to other nodes
|
||||
std::deque<RN_EDGE_MST_PTR> m_Edges;
|
||||
} RN_ZONE_DATA;
|
||||
|
||||
///> Structureo to hold ratsnest data for D_PAD objects.
|
||||
typedef struct
|
||||
{
|
||||
///> Node representing the pad.
|
||||
RN_NODE_PTR m_Node;
|
||||
|
||||
///> Helper nodes that make for connections to items located in the pad area.
|
||||
std::deque<RN_EDGE_MST_PTR> m_Edges;
|
||||
} RN_PAD_DATA;
|
||||
|
||||
///> Helper typedefs
|
||||
typedef std::unordered_map<const D_PAD*, RN_PAD_DATA> PAD_NODE_MAP;
|
||||
typedef std::unordered_map<const VIA*, RN_NODE_PTR> VIA_NODE_MAP;
|
||||
typedef std::unordered_map<const TRACK*, RN_EDGE_MST_PTR> TRACK_EDGE_MAP;
|
||||
typedef std::unordered_map<const ZONE_CONTAINER*, RN_ZONE_DATA> ZONE_DATA_MAP;
|
||||
|
||||
///> Map that associates nodes in the ratsnest model to respective nodes.
|
||||
PAD_NODE_MAP m_pads;
|
||||
|
||||
///> Map that associates nodes in the ratsnest model to respective vias.
|
||||
VIA_NODE_MAP m_vias;
|
||||
|
||||
///> Map that associates edges in the ratsnest model to respective tracks.
|
||||
TRACK_EDGE_MAP m_tracks;
|
||||
|
||||
///> Map that associates groups of subpolygons in the ratsnest model to respective zones.
|
||||
ZONE_DATA_MAP m_zones;
|
||||
|
||||
///> Visibility flag.
|
||||
bool m_visible;
|
||||
|
||||
class TRIANGULATOR_STATE;
|
||||
|
||||
std::shared_ptr<TRIANGULATOR_STATE> m_triangulator;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class RN_DATA
|
||||
*
|
||||
* Stores information about unconnected items for a board.
|
||||
*/
|
||||
class RN_DATA
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
* @param aBoard is the board to be processed in order to look for unconnected items.
|
||||
*/
|
||||
RN_DATA( const BOARD* aBoard ) : m_board( aBoard ) {}
|
||||
|
||||
/**
|
||||
* Function Add()
|
||||
* Adds an item to the ratsnest data.
|
||||
* @param aItem is an item to be added.
|
||||
* @return True if operation succeeded.
|
||||
*/
|
||||
bool Add( const BOARD_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function Remove()
|
||||
* Removes an item from the ratsnest data.
|
||||
* @param aItem is an item to be updated.
|
||||
* @return True if operation succeeded.
|
||||
*/
|
||||
bool Remove( const BOARD_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function Update()
|
||||
* Updates the ratsnest 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 Update( const BOARD_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function AddSimple()
|
||||
* Sets an item to be drawn in simple mode (i.e. one line per node, instead of full ratsnest).
|
||||
* It is used for drawing quick, temporary ratsnest, eg. while moving an item.
|
||||
* @param aItem is an item to be drawn in simple node.
|
||||
*/
|
||||
void AddSimple( const BOARD_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function AddBlocked()
|
||||
* Specifies an item as not suitable as a ratsnest line target (i.e. ratsnest lines will not
|
||||
* target its node(s)). The status is cleared after calling ClearSimple().
|
||||
* @param aItem is the item of which node(s) are not going to be used as a ratsnest line target.
|
||||
*/
|
||||
void AddBlocked( const BOARD_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function ClearSimple()
|
||||
* Clears the list of nodes for which ratsnest is drawn in simple mode (one line per node).
|
||||
*/
|
||||
void ClearSimple()
|
||||
{
|
||||
for( RN_NET& net : m_nets )
|
||||
net.ClearSimple();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function ProcessBoard()
|
||||
* Prepares data for computing (computes a list of current nodes and connections). It is
|
||||
* required to run only once after loading a board.
|
||||
*/
|
||||
void ProcessBoard();
|
||||
|
||||
/**
|
||||
* Function Recalculate()
|
||||
* Recomputes ratsnest for selected net number or all nets that need updating.
|
||||
* @param aNet is a net number. If it is negative, all nets that need updating are recomputed.
|
||||
*/
|
||||
void Recalculate( int aNet = -1 );
|
||||
|
||||
/**
|
||||
* Function GetNetCount()
|
||||
* Returns the number of nets handled by the ratsnest.
|
||||
* @return Number of the nets.
|
||||
*/
|
||||
int GetNetCount() const
|
||||
{
|
||||
return m_nets.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetNet()
|
||||
* Returns ratsnest grouped by net numbers.
|
||||
* @param aNetCode is the net code.
|
||||
* @return Ratsnest data for a specified net.
|
||||
*/
|
||||
RN_NET& GetNet( int aNetCode )
|
||||
{
|
||||
assert( aNetCode > 0 ); // ratsnest does not handle the unconnected net
|
||||
|
||||
return m_nets[aNetCode];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function GetConnectedItems()
|
||||
* Adds items that are connected together to a list.
|
||||
* @param aItem is the reference item to find other connected items.
|
||||
* @param aOutput is the list that will contain found items.
|
||||
* @param aTypes allows to filter by item types.
|
||||
*/
|
||||
void GetConnectedItems( const BOARD_CONNECTED_ITEM* aItem,
|
||||
std::list<BOARD_CONNECTED_ITEM*>& aOutput,
|
||||
RN_ITEM_TYPE aTypes = RN_ALL ) const;
|
||||
|
||||
/**
|
||||
* Function GetNetItems()
|
||||
* Adds all items that belong to a certain net to a list.
|
||||
* @param aNetCode is the net code.
|
||||
* @param aOutput is the list that will have items added.
|
||||
* @param aTypes allows to filter by item types.
|
||||
*/
|
||||
void GetNetItems( int aNetCode, std::list<BOARD_CONNECTED_ITEM*>& aOutput,
|
||||
RN_ITEM_TYPE aTypes = RN_ALL ) const;
|
||||
|
||||
/**
|
||||
* Function AreConnected()
|
||||
* Checks if two items are connected with copper.
|
||||
* @param aItem is the first item.
|
||||
* @param aOther is the second item.
|
||||
* @return true if they are connected, false otherwise.
|
||||
*/
|
||||
bool AreConnected( const BOARD_CONNECTED_ITEM* aItem, const BOARD_CONNECTED_ITEM* aOther );
|
||||
|
||||
/**
|
||||
* Function GetUnconnectedCount()
|
||||
* Returns the number of missing connections.
|
||||
* @return Number of missing connections.
|
||||
*/
|
||||
int GetUnconnectedCount() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Function updateNet()
|
||||
* Recomputes ratsnest for a single net.
|
||||
* @param aNetCode is the net number to be recomputed.
|
||||
*/
|
||||
void updateNet( int aNetCode );
|
||||
|
||||
///> Board to be processed.
|
||||
const BOARD* m_board;
|
||||
|
||||
///> Stores information about ratsnest grouped by net numbers.
|
||||
std::vector<RN_NET> m_nets;
|
||||
};
|
||||
|
||||
#endif /* RATSNEST_DATA_H */
|
||||
|
|
|
@ -29,15 +29,18 @@
|
|||
|
||||
#include <ratsnest_viewitem.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <pcb_painter.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <view/view.h>
|
||||
|
||||
namespace KIGFX {
|
||||
|
||||
RATSNEST_VIEWITEM::RATSNEST_VIEWITEM( RN_DATA* aData ) :
|
||||
RATSNEST_VIEWITEM::RATSNEST_VIEWITEM( std::shared_ptr<CONNECTIVITY_DATA> aData ) :
|
||||
EDA_ITEM( NOT_USED ), m_data( aData )
|
||||
{
|
||||
}
|
||||
|
@ -52,65 +55,78 @@ const BOX2I RATSNEST_VIEWITEM::ViewBBox() const
|
|||
return bbox;
|
||||
}
|
||||
|
||||
#include <geometry/seg.h>
|
||||
std::vector<SEG> delEdges;
|
||||
|
||||
void clearDEdges() { delEdges.clear(); }
|
||||
void addDEdge ( SEG edge ) { delEdges.push_back(edge); }
|
||||
|
||||
|
||||
void RATSNEST_VIEWITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
|
||||
{
|
||||
static const double crossSize = 100000.0;
|
||||
|
||||
auto gal = aView->GetGAL();
|
||||
gal->SetIsStroke( true );
|
||||
gal->SetIsFill( false );
|
||||
gal->SetLineWidth( 1.0 );
|
||||
auto rs = aView->GetPainter()->GetSettings();
|
||||
auto color = rs->GetColor( NULL, LAYER_RATSNEST );
|
||||
|
||||
int highlightedNet = rs->GetHighlightNetCode();
|
||||
|
||||
gal->SetStrokeColor( color.Brightened( 0.8 ) );
|
||||
for (auto s : delEdges)
|
||||
gal->DrawLine( s.A, s.B );
|
||||
|
||||
|
||||
// Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved)
|
||||
for( const auto& l : m_data->GetDynamicRatsnest() )
|
||||
{
|
||||
if ( l.a == l.b )
|
||||
{
|
||||
gal->DrawLine( VECTOR2I( l.a.x - crossSize, l.a.y - crossSize ), VECTOR2I( l.b.x + crossSize, l.b.y + crossSize ) );
|
||||
gal->DrawLine( VECTOR2I( l.a.x - crossSize, l.a.y + crossSize ), VECTOR2I( l.b.x + crossSize, l.b.y - crossSize ) );
|
||||
} else {
|
||||
gal->DrawLine( l.a, l.b );
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamic ratsnest (for e.g. dragged items)
|
||||
for( int i = 1; i < m_data->GetNetCount(); ++i )
|
||||
{
|
||||
RN_NET& net = m_data->GetNet( i );
|
||||
RN_NET* net = m_data->GetRatsnestForNet( i );
|
||||
|
||||
if( !net.IsVisible() )
|
||||
if( !net->IsVisible() )
|
||||
continue;
|
||||
|
||||
// Set brighter color for the temporary ratsnest
|
||||
gal->SetStrokeColor( color.Brightened( 0.8 ) );
|
||||
|
||||
// Draw the "dynamic" ratsnest (i.e. for objects that may be currently being moved)
|
||||
for( const RN_NODE_PTR& node : net.GetSimpleNodes() )
|
||||
{
|
||||
// Skipping nodes with higher reference count avoids displaying redundant lines
|
||||
if( node->GetRefCount() > 1 )
|
||||
continue;
|
||||
|
||||
RN_NODE_PTR dest = net.GetClosestNode( node, LINE_TARGET() );
|
||||
|
||||
if( dest )
|
||||
{
|
||||
VECTOR2D origin( node->GetX(), node->GetY() );
|
||||
VECTOR2D end( dest->GetX(), dest->GetY() );
|
||||
|
||||
gal->DrawLine( origin, end );
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the "static" ratsnest
|
||||
if( i != highlightedNet )
|
||||
gal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted
|
||||
|
||||
const std::vector<RN_EDGE_MST_PTR>* edges = net.GetUnconnected();
|
||||
|
||||
if( edges == NULL )
|
||||
continue;
|
||||
|
||||
for( const RN_EDGE_MST_PTR& edge : *edges )
|
||||
for( const auto& edge : net->GetUnconnected() )
|
||||
{
|
||||
const RN_NODE_PTR& sourceNode = edge->GetSourceNode();
|
||||
const RN_NODE_PTR& targetNode = edge->GetTargetNode();
|
||||
VECTOR2D source( sourceNode->GetX(), sourceNode->GetY() );
|
||||
VECTOR2D target( targetNode->GetX(), targetNode->GetY() );
|
||||
const auto& sourceNode = edge.GetSourceNode();
|
||||
const auto& targetNode = edge.GetTargetNode();
|
||||
const VECTOR2I source( sourceNode->Pos() );
|
||||
const VECTOR2I target( targetNode->Pos() );
|
||||
|
||||
if ( !sourceNode->GetNoLine() && !targetNode->GetNoLine() )
|
||||
{
|
||||
if ( source == target )
|
||||
{
|
||||
constexpr int CROSS_SIZE = 200000;
|
||||
|
||||
gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y - CROSS_SIZE ), VECTOR2I( source.x + CROSS_SIZE, source.y + CROSS_SIZE ) );
|
||||
gal->DrawLine( VECTOR2I( source.x - CROSS_SIZE, source.y + CROSS_SIZE ), VECTOR2I( source.x + CROSS_SIZE, source.y - CROSS_SIZE ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
gal->DrawLine( source, target );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,18 +30,19 @@
|
|||
#ifndef RATSNEST_VIEWITEM_H
|
||||
#define RATSNEST_VIEWITEM_H
|
||||
|
||||
#include <memory>
|
||||
#include <base_struct.h>
|
||||
#include <math/vector2d.h>
|
||||
|
||||
class GAL;
|
||||
class RN_DATA;
|
||||
class CONNECTIVITY_DATA;
|
||||
|
||||
namespace KIGFX
|
||||
{
|
||||
class RATSNEST_VIEWITEM : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
RATSNEST_VIEWITEM( RN_DATA* aData );
|
||||
RATSNEST_VIEWITEM( std::shared_ptr<CONNECTIVITY_DATA> aData );
|
||||
|
||||
/// @copydoc VIEW_ITEM::ViewBBox()
|
||||
const BOX2I ViewBBox() const override;
|
||||
|
@ -69,7 +70,7 @@ public:
|
|||
|
||||
protected:
|
||||
///> Object containing ratsnest data.
|
||||
RN_DATA* m_data;
|
||||
std::shared_ptr<CONNECTIVITY_DATA> m_data;
|
||||
};
|
||||
|
||||
} // namespace KIGFX
|
||||
|
|
|
@ -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>();
|
||||
}
|
|
@ -42,7 +42,7 @@
|
|||
#include <view/view_controls.h>
|
||||
#include <view/view.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <confirm.h>
|
||||
#include <bitmaps.h>
|
||||
#include <hotkeys.h>
|
||||
|
@ -301,6 +301,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
static_cast<BOARD_ITEM*>( item )->Move( movement + m_offset );
|
||||
}
|
||||
|
||||
updateRatsnest( true );
|
||||
}
|
||||
else if( !m_dragging ) // Prepare to start dragging
|
||||
{
|
||||
|
@ -410,6 +412,7 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
// Update dragging offset (distance between cursor and the first dragged item)
|
||||
m_offset = static_cast<BOARD_ITEM*>( selection.Front() )->GetPosition() - modPoint;
|
||||
getView()->Update( &selection );
|
||||
updateRatsnest( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,6 +425,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
} while( ( evt = Wait() ) ); //Should be assignment not equality test
|
||||
|
||||
getModel<BOARD>()->GetConnectivity()->ClearDynamicRatsnest();
|
||||
|
||||
controls->ForceCursorPosition( false );
|
||||
controls->ShowCursor( false );
|
||||
controls->SetSnapping( false );
|
||||
|
@ -516,6 +521,8 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( !m_dragging )
|
||||
m_commit->Push( _( "Rotate" ) );
|
||||
else
|
||||
updateRatsnest( true );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
@ -622,6 +629,8 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( !m_dragging )
|
||||
m_commit->Push( _( "Mirror" ) );
|
||||
else
|
||||
updateRatsnest( true );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
@ -655,6 +664,8 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
|
|||
|
||||
if( !m_dragging )
|
||||
m_commit->Push( _( "Flip" ) );
|
||||
else
|
||||
updateRatsnest( true );
|
||||
|
||||
if( selection.IsHover() )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
@ -1138,6 +1149,17 @@ void EDIT_TOOL::SetTransitions()
|
|||
Go( &EDIT_TOOL::MeasureTool, PCB_ACTIONS::measureTool.MakeEvent() );
|
||||
}
|
||||
|
||||
void EDIT_TOOL::updateRatsnest( bool aRedraw )
|
||||
{
|
||||
auto& selection = m_selectionTool->GetSelection();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
std::vector<BOARD_ITEM *> items;
|
||||
|
||||
for ( auto item : selection )
|
||||
items.push_back ( static_cast<BOARD_ITEM *>( item ) );
|
||||
|
||||
connectivity->ComputeDynamicRatsnest( items );
|
||||
}
|
||||
|
||||
wxPoint EDIT_TOOL::getModificationPoint( const SELECTION& aSelection )
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
class BOARD_COMMIT;
|
||||
class BOARD_ITEM;
|
||||
class SELECTION_TOOL;
|
||||
class CONNECTIVITY_DATA;
|
||||
|
||||
/**
|
||||
* Class EDIT_TOOL
|
||||
|
@ -144,6 +145,13 @@ private:
|
|||
///> of edit reference point).
|
||||
VECTOR2I m_cursor;
|
||||
|
||||
std::unique_ptr<CONNECTIVITY_DATA> m_dynamicConnectivity;
|
||||
|
||||
///> Updates ratsnest for selected items.
|
||||
///> @param aRedraw says if selected items should be drawn using the simple mode (e.g. one line
|
||||
///> per item).
|
||||
void updateRatsnest( bool aRedraw );
|
||||
|
||||
///> Returns the right modification point (e.g. for rotation), depending on the number of
|
||||
///> selected items.
|
||||
wxPoint getModificationPoint( const SELECTION& aSelection );
|
||||
|
|
|
@ -356,6 +356,7 @@ public:
|
|||
static TOOL_ACTION crossProbeSchToPcb;
|
||||
static TOOL_ACTION appendBoard;
|
||||
static TOOL_ACTION showHelp;
|
||||
static TOOL_ACTION showLocalRatsnest;
|
||||
static TOOL_ACTION toBeDone;
|
||||
|
||||
/// Find an item
|
||||
|
|
|
@ -41,8 +41,7 @@
|
|||
#include <class_draw_panel_gal.h>
|
||||
#include <class_module.h>
|
||||
#include <class_mire.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <collectors.h>
|
||||
#include <zones_functions_for_undo_redo.h>
|
||||
#include <board_commit.h>
|
||||
|
@ -481,6 +480,11 @@ int PCB_EDITOR_CONTROL::PlaceModule( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
controls->ShowCursor( false );
|
||||
controls->SetSnapping( false );
|
||||
controls->SetAutoPan( false );
|
||||
controls->CaptureCursor( false );
|
||||
|
||||
view->Remove( &preview );
|
||||
m_frame->SetNoToolSelected();
|
||||
|
||||
|
@ -637,7 +641,7 @@ int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
|
@ -651,13 +655,11 @@ int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent )
|
|||
|
||||
m_frame->Fill_Zone( zone );
|
||||
zone->SetIsFilled( true );
|
||||
ratsnest->Update( zone );
|
||||
getView()->Update( zone );
|
||||
}
|
||||
|
||||
commit.Push( _( "Fill Zone" ) );
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -666,7 +668,7 @@ int PCB_EDITOR_CONTROL::ZoneFill( const TOOL_EVENT& aEvent )
|
|||
int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>();
|
||||
RN_DATA* ratsnest = board->GetRatsnest();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
|
@ -678,13 +680,11 @@ int PCB_EDITOR_CONTROL::ZoneFillAll( const TOOL_EVENT& aEvent )
|
|||
|
||||
m_frame->Fill_Zone( zone );
|
||||
zone->SetIsFilled( true );
|
||||
ratsnest->Update( zone );
|
||||
getView()->Update( zone );
|
||||
}
|
||||
|
||||
commit.Push( _( "Fill All Zones" ) );
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -694,7 +694,7 @@ int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
|
||||
const auto& selection = selTool->GetSelection();
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
|
@ -708,13 +708,11 @@ int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
|||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
ratsnest->Update( zone );
|
||||
getView()->Update( zone );
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill Zone" ) );
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -723,7 +721,7 @@ int PCB_EDITOR_CONTROL::ZoneUnfill( const TOOL_EVENT& aEvent )
|
|||
int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>();
|
||||
RN_DATA* ratsnest = board->GetRatsnest();
|
||||
auto connectivity = getModel<BOARD>()->GetConnectivity();
|
||||
|
||||
BOARD_COMMIT commit( this );
|
||||
|
||||
|
@ -735,13 +733,11 @@ int PCB_EDITOR_CONTROL::ZoneUnfillAll( const TOOL_EVENT& aEvent )
|
|||
|
||||
zone->SetIsFilled( false );
|
||||
zone->ClearFilledPolysList();
|
||||
ratsnest->Update( zone );
|
||||
getView()->Update( zone );
|
||||
}
|
||||
|
||||
commit.Push( _( "Unfill All Zones" ) );
|
||||
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -808,6 +804,8 @@ int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent )
|
|||
|
||||
netcode = curr_area->GetNetCode();
|
||||
|
||||
if( firstZone )
|
||||
{
|
||||
if( firstZone->GetNetCode() != netcode )
|
||||
continue;
|
||||
|
||||
|
@ -825,6 +823,11 @@ int PCB_EDITOR_CONTROL::ZoneMerge( const TOOL_EVENT& aEvent )
|
|||
|
||||
toMerge.push_back( curr_area );
|
||||
}
|
||||
else
|
||||
{
|
||||
toMerge.push_back( curr_area );
|
||||
}
|
||||
}
|
||||
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
|
@ -1055,6 +1058,31 @@ int PCB_EDITOR_CONTROL::HighlightNetCursor( const TOOL_EVENT& aEvent )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool showLocalRatsnest( KIGFX::VIEW* aView, PCB_BASE_FRAME* aFrame,
|
||||
KIGFX::ORIGIN_VIEWITEM* aItem, const VECTOR2D& aPosition )
|
||||
{
|
||||
aFrame->SetAuxOrigin( wxPoint( aPosition.x, aPosition.y ) );
|
||||
aItem->SetPosition( aPosition );
|
||||
aView->MarkDirty();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int PCB_EDITOR_CONTROL::ShowLocalRatsnest( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
Activate();
|
||||
|
||||
auto picker = m_toolMgr->GetTool<PICKER_TOOL>();
|
||||
assert( picker );
|
||||
|
||||
m_frame->SetToolID( ID_PCB_SHOW_1_RATSNEST_BUTT, wxCURSOR_PENCIL, _( "Pick Components for Local Ratsnest" ) );
|
||||
//picker->SetClickHandler( std::bind( showLocalRatsnest, m_toolMgr, _1 ) );
|
||||
picker->SetSnapping( false );
|
||||
picker->Activate();
|
||||
Wait();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PCB_EDITOR_CONTROL::UpdateSelectionRatsnest( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
#include <pcbnew_id.h>
|
||||
#include <wxPcbStruct.h>
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <view/view_controls.h>
|
||||
|
|
|
@ -43,7 +43,7 @@ using namespace std::placeholders;
|
|||
#include <class_zone.h>
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
// Point editor
|
||||
TOOL_ACTION PCB_ACTIONS::pointEditorAddCorner( "pcbnew.PointEditor.addCorner",
|
||||
|
@ -551,7 +551,7 @@ void POINT_EDITOR::finishItem() const
|
|||
if( zone->IsFilled() )
|
||||
{
|
||||
getEditFrame<PCB_EDIT_FRAME>()->Fill_Zone( zone );
|
||||
zone->GetBoard()->GetRatsnest()->Recalculate( zone->GetNetCode() );
|
||||
// zone->GetBoard()->GetRatsnest()->Recalculate( zone->GetNetCode() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ using namespace std::placeholders;
|
|||
|
||||
#include <tool/tool_event.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include "selection_tool.h"
|
||||
#include "pcb_bright_box.h"
|
||||
|
@ -830,24 +830,24 @@ void SELECTION_TOOL::selectAllItemsConnectedToTrack( TRACK& aSourceTrack )
|
|||
|
||||
void SELECTION_TOOL::selectAllItemsConnectedToItem( BOARD_CONNECTED_ITEM& aSourceItem )
|
||||
{
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
std::list<BOARD_CONNECTED_ITEM*> itemsList;
|
||||
ratsnest->GetConnectedItems( &aSourceItem, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
|
||||
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
|
||||
auto connectivity = board()->GetConnectivity();
|
||||
|
||||
for( BOARD_CONNECTED_ITEM* i : itemsList )
|
||||
select( i );
|
||||
std::list<BOARD_CONNECTED_ITEM*> items;
|
||||
items = connectivity->GetConnectedItems( &aSourceItem, types );
|
||||
|
||||
for( auto item : connectivity->GetConnectedItems( &aSourceItem, types ) )
|
||||
select( item );
|
||||
}
|
||||
|
||||
|
||||
void SELECTION_TOOL::selectAllItemsOnNet( int aNetCode )
|
||||
{
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
std::list<BOARD_CONNECTED_ITEM*> itemsList;
|
||||
constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_VIA_T, EOT };
|
||||
auto connectivity = board()->GetConnectivity();
|
||||
|
||||
ratsnest->GetNetItems( aNetCode, itemsList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
|
||||
|
||||
for( BOARD_CONNECTED_ITEM* i : itemsList )
|
||||
select( i );
|
||||
for( auto item : connectivity->GetNetItems( aNetCode, types ) )
|
||||
select( item );
|
||||
}
|
||||
|
||||
|
||||
|
@ -913,12 +913,12 @@ void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetpath )
|
|||
// now we need to find all modules that are connected to each of these nets
|
||||
// then we need to determine if these modules are in the list of modules
|
||||
// belonging to this sheet ( modList )
|
||||
RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
//RN_DATA* ratsnest = getModel<BOARD>()->GetRatsnest();
|
||||
std::list<int> removeCodeList;
|
||||
for( int netCode : netcodeList )
|
||||
{
|
||||
std::list<BOARD_CONNECTED_ITEM*> netPads;
|
||||
ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) );
|
||||
// ratsnest->GetNetItems( netCode, netPads, (RN_ITEM_TYPE)( RN_PADS ) );
|
||||
for( BOARD_CONNECTED_ITEM* mitem : netPads )
|
||||
{
|
||||
bool found = ( std::find( modList.begin(), modList.end(), mitem->GetParent() ) != modList.end() );
|
||||
|
@ -945,7 +945,7 @@ void SELECTION_TOOL::selectAllItemsOnSheet( wxString& aSheetpath )
|
|||
std::list<BOARD_CONNECTED_ITEM*> localConnectionList;
|
||||
for( int netCode : netcodeList )
|
||||
{
|
||||
ratsnest->GetNetItems( netCode, localConnectionList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
|
||||
//ratsnest->GetNetItems( netCode, localConnectionList, (RN_ITEM_TYPE)( RN_TRACKS | RN_VIAS ) );
|
||||
}
|
||||
|
||||
for( BOARD_ITEM* i : modList )
|
||||
|
|
|
@ -45,7 +45,7 @@ using namespace std::placeholders;
|
|||
#include <class_zone.h>
|
||||
#include <class_edge_mod.h>
|
||||
|
||||
#include <ratsnest_data.h>
|
||||
#include <connectivity.h>
|
||||
|
||||
#include <tools/selection_tool.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
@ -383,7 +383,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
bool deep_reBuild_ratsnest = false; // true later if pointers must be rebuilt
|
||||
|
||||
KIGFX::VIEW* view = GetGalCanvas()->GetView();
|
||||
RN_DATA* ratsnest = GetBoard()->GetRatsnest();
|
||||
auto connectivity = GetBoard()->GetConnectivity();
|
||||
|
||||
// Undo in the reverse order of list creation: (this can allow stacked changes
|
||||
// like the same item can be changes and deleted in the same complex command
|
||||
|
@ -468,7 +468,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
}
|
||||
|
||||
view->Remove( item );
|
||||
ratsnest->Remove( item );
|
||||
connectivity->Remove( item );
|
||||
|
||||
item->SwapData( image );
|
||||
|
||||
|
@ -482,7 +482,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
}
|
||||
|
||||
view->Add( item );
|
||||
ratsnest->Add( item );
|
||||
connectivity->Add( item );
|
||||
item->ClearFlags();
|
||||
|
||||
}
|
||||
|
@ -518,27 +518,27 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
case UR_MOVED:
|
||||
item->Move( aRedoCommand ? aList->m_TransformPoint : -aList->m_TransformPoint );
|
||||
view->Update( item, KIGFX::GEOMETRY );
|
||||
ratsnest->Update( item );
|
||||
connectivity->Update( item );
|
||||
break;
|
||||
|
||||
case UR_ROTATED:
|
||||
item->Rotate( aList->m_TransformPoint,
|
||||
aRedoCommand ? m_rotationAngle : -m_rotationAngle );
|
||||
view->Update( item, KIGFX::GEOMETRY );
|
||||
ratsnest->Update( item );
|
||||
connectivity->Update( item );
|
||||
break;
|
||||
|
||||
case UR_ROTATED_CLOCKWISE:
|
||||
item->Rotate( aList->m_TransformPoint,
|
||||
aRedoCommand ? -m_rotationAngle : m_rotationAngle );
|
||||
view->Update( item, KIGFX::GEOMETRY );
|
||||
ratsnest->Update( item );
|
||||
connectivity->Update( item );
|
||||
break;
|
||||
|
||||
case UR_FLIPPED:
|
||||
item->Flip( aList->m_TransformPoint );
|
||||
view->Update( item, KIGFX::LAYERS );
|
||||
ratsnest->Update( item );
|
||||
connectivity->Update( item );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -555,7 +555,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
if( not_found )
|
||||
wxMessageBox( wxT( "Incomplete undo/redo operation: some items not found" ) );
|
||||
|
||||
// Rebuild pointers and ratsnest that can be changed.
|
||||
// Rebuild pointers and connectivity that can be changed.
|
||||
if( reBuild_ratsnest )
|
||||
{
|
||||
// Compile ratsnest propagates nets from pads to tracks
|
||||
|
@ -565,10 +565,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
|
|||
|
||||
if( IsGalCanvasActive() )
|
||||
{
|
||||
if( deep_reBuild_ratsnest )
|
||||
ratsnest->ProcessBoard();
|
||||
else
|
||||
ratsnest->Recalculate();
|
||||
connectivity->RecalculateRatsnest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,8 @@
|
|||
#include <pcbnew.h>
|
||||
#include <zones.h>
|
||||
|
||||
#include <view/view.h>
|
||||
#include <connectivity.h>
|
||||
#include <board_commit.h>
|
||||
|
||||
#define FORMAT_STRING _( "Filling zone %d out of %d (net %s)..." )
|
||||
|
||||
|
@ -116,11 +117,15 @@ int PCB_EDIT_FRAME::Fill_Zone( ZONE_CONTAINER* aZone )
|
|||
|
||||
wxBusyCursor dummy; // Shows an hourglass cursor (removed by its destructor)
|
||||
|
||||
BOARD_COMMIT commit ( this );
|
||||
commit.Modify( aZone );
|
||||
aZone->BuildFilledSolidAreasPolygons( GetBoard() );
|
||||
GetGalCanvas()->GetView()->Update( aZone, KIGFX::ALL );
|
||||
GetBoard()->GetRatsnest()->Update( aZone );
|
||||
commit.Push ( _("Fill Zone"), false );
|
||||
|
||||
OnModify();
|
||||
//GetGalCanvas()->GetView()->Update( aZone, KIGFX::ALL );
|
||||
//GetBoard()->GetConnectivity()->Update( aZone );
|
||||
|
||||
//OnModify();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
* To emit zone data to a file when filling zones for the debugging purposes,
|
||||
* set this 'true' and build.
|
||||
*/
|
||||
static const bool g_DumpZonesWhenFilling = false;
|
||||
static const bool g_DumpZonesWhenFilling = true;
|
||||
|
||||
extern void BuildUnconnectedThermalStubsPolygonList( SHAPE_POLY_SET& aCornerBuffer,
|
||||
BOARD* aPcb, ZONE_CONTAINER* aZone,
|
||||
|
@ -437,6 +437,8 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb )
|
|||
|
||||
SHAPE_POLY_SET solidAreas = *m_smoothedPoly;
|
||||
|
||||
printf("VC %d\n", solidAreas.VertexCount());
|
||||
|
||||
solidAreas.Inflate( -outline_half_thickness, segsPerCircle );
|
||||
solidAreas.Simplify( POLY_CALC_MODE );
|
||||
|
||||
|
@ -473,10 +475,6 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb )
|
|||
|
||||
m_FilledPolysList = areas_fractured;
|
||||
|
||||
// Remove insulated islands:
|
||||
if( GetNetCode() > 0 )
|
||||
TestForCopperIslandAndRemoveInsulatedIslands( aPcb );
|
||||
|
||||
SHAPE_POLY_SET thermalHoles;
|
||||
|
||||
// Test thermal stubs connections and add polygons to remove unconnected stubs.
|
||||
|
@ -506,9 +504,12 @@ void ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb )
|
|||
|
||||
m_FilledPolysList = th_fractured;
|
||||
|
||||
}
|
||||
|
||||
m_RawPolysList = m_FilledPolysList;
|
||||
|
||||
if( GetNetCode() > 0 )
|
||||
TestForCopperIslandAndRemoveInsulatedIslands( aPcb );
|
||||
}
|
||||
|
||||
if(g_DumpZonesWhenFilling)
|
||||
dumper->EndGroup();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
|
||||
* Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -25,78 +25,24 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <fctsys.h>
|
||||
#include <common.h>
|
||||
|
||||
#include <class_board.h>
|
||||
#include <class_module.h>
|
||||
#include <class_track.h>
|
||||
#include <class_zone.h>
|
||||
|
||||
#include <pcbnew.h>
|
||||
#include <zones.h>
|
||||
#include <polygon_test_point_inside.h>
|
||||
|
||||
#include <connectivity.h>
|
||||
|
||||
void ZONE_CONTAINER::TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb )
|
||||
{
|
||||
if( m_FilledPolysList.IsEmpty() )
|
||||
return;
|
||||
std::vector<int> islands;
|
||||
|
||||
// Build a list of points connected to the net:
|
||||
// list of coordinates of pads and vias on this layer and on this net.
|
||||
std::vector <wxPoint> listPointsCandidates;
|
||||
auto connectivity = aPcb->GetConnectivity();
|
||||
|
||||
for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
|
||||
connectivity->FindIsolatedCopperIslands( this, islands );
|
||||
|
||||
std::sort( islands.begin(), islands.end(), std::greater<int>() );
|
||||
|
||||
for( auto idx : islands )
|
||||
{
|
||||
for( D_PAD* pad = module->Pads(); pad != NULL; pad = pad->Next() )
|
||||
{
|
||||
if( !pad->IsOnLayer( GetLayer() ) )
|
||||
continue;
|
||||
|
||||
if( pad->GetNetCode() != GetNetCode() )
|
||||
continue;
|
||||
|
||||
listPointsCandidates.push_back( pad->GetPosition() );
|
||||
}
|
||||
m_FilledPolysList.DeletePolygon( idx );
|
||||
}
|
||||
|
||||
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
|
||||
{
|
||||
if( !track->IsOnLayer( GetLayer() ) )
|
||||
continue;
|
||||
|
||||
if( track->GetNetCode() != GetNetCode() )
|
||||
continue;
|
||||
|
||||
listPointsCandidates.push_back( track->GetStart() );
|
||||
|
||||
if( track->Type() != PCB_VIA_T )
|
||||
listPointsCandidates.push_back( track->GetEnd() );
|
||||
}
|
||||
|
||||
// test if a point is inside
|
||||
|
||||
for( int outline = 0; outline < m_FilledPolysList.OutlineCount(); outline++ )
|
||||
{
|
||||
bool connected = false;
|
||||
|
||||
for( unsigned ic = 0; ic < listPointsCandidates.size(); ic++ )
|
||||
{
|
||||
// test if this area is connected to a board item:
|
||||
wxPoint pos = listPointsCandidates[ic];
|
||||
|
||||
if( m_FilledPolysList.Contains( VECTOR2I( pos.x, pos.y ), outline ) )
|
||||
{
|
||||
connected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( !connected ) // this polygon is connected: analyse next polygon
|
||||
{
|
||||
m_FilledPolysList.DeletePolygon( outline );
|
||||
outline--;
|
||||
}
|
||||
}
|
||||
connectivity->Update( this );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue