7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 00:21:25 +00:00

Pcbnew: Enhanced algorithm to calculate board connections:

* A track is seen connected to a pad if the track end is inside the pad shape.
* Pads inside pads are now seen connected, if the center of the pad is *inside* the other pad.
* this is made to be sure a large copper area is shared by the 2 pads,  and to keep algorithm fast.
This commit is contained in:
jean-pierre charras 2011-12-19 12:58:24 +01:00
parent ccb910eb62
commit d41b81fc3b
8 changed files with 620 additions and 18 deletions

View File

@ -4,6 +4,19 @@ KiCad ChangeLog 2011
Please add newer entries at the top, list the date and your name with
email address.
2011-Dec-19, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
Pcbnew:
Enhanced algorithms to calculate board connections:
- A track is seen connected to a pad if the track end is inside the pad shape.
- Pads inside pads are now seen connected, if the center of the pad is
*inside* the other pad.
(this is made to be sure a large copper area is shared by the 2 pads,
and to keep algorithm fast).
Algorithm to calculate pads connections is still very fast.
However some other functions (drag pads, track len calculation ...)
still need the track end exactly on the pad position.
2011-Dec-13 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================

View File

@ -0,0 +1,16 @@
EESchema-LIBRARY Version 2.3 Date: 19/12/2011 12:55:30
#encoding utf-8
#
# CONN_1
#
DEF ~CONN_1 P 0 30 N N 1 F N
F0 "P" 80 0 40 H V L CNN
F1 "CONN_1" 0 55 30 H I C CNN
DRAW
C 0 0 31 0 1 0 N
P 2 0 1 0 -30 0 -50 0 N
X 1 1 -150 0 100 R 60 60 1 1 P
ENDDRAW
ENDDEF
#
#End Library

View File

LOADING design file

View File

@ -0,0 +1,31 @@
Cmp-Mod V01 Created by CvPcb (2011-12-09 BZR 3290)-testing date = 11/12/2011 20:34:04
BeginCmp
TimeStamp = /4EDF7CC5;
Reference = P1;
ValeurCmp = CONN_1;
IdModule = 1pin;
EndCmp
BeginCmp
TimeStamp = /4EDF7CC0;
Reference = P2;
ValeurCmp = CONN_1;
IdModule = 1pin;
EndCmp
BeginCmp
TimeStamp = /4EE5056C;
Reference = P3;
ValeurCmp = CONN_1;
IdModule = 1pin;
EndCmp
BeginCmp
TimeStamp = /4EE5056D;
Reference = P4;
ValeurCmp = CONN_1;
IdModule = 1pin;
EndCmp
EndListe

View File

@ -0,0 +1,25 @@
# EESchema Netlist Version 1.1 created 19/12/2011 12:55:28
(
( /4EE5056D $noname P4 CONN_1 {Lib=CONN_1}
( 1 /NET1 )
)
( /4EE5056C $noname P3 CONN_1 {Lib=CONN_1}
( 1 /NET1 )
)
( /4EDF7CC5 $noname P1 CONN_1 {Lib=CONN_1}
( 1 /NET2 )
)
( /4EDF7CC0 $noname P2 CONN_1 {Lib=CONN_1}
( 1 /NET2 )
)
)
*
{ Pin List by Nets
Net 1 "/NET1" "NET1"
P4 1
P3 1
Net 2 "/NET2" "NET2"
P1 1
P2 1
}
#End

View File

@ -0,0 +1,108 @@
update=13/12/2011 11:04:14
version=1
last_client=pcbnew
[cvpcb]
version=1
NetITyp=0
NetIExt=.net
PkgIExt=.pkg
NetDir=
LibDir=
NetType=0
[cvpcb/libraries]
EquName1=devcms
[eeschema]
version=1
LibDir=
NetFmt=1
HPGLSpd=20
HPGLDm=15
HPGLNum=1
offX_A4=0
offY_A4=0
offX_A3=0
offY_A3=0
offX_A2=0
offY_A2=0
offX_A1=0
offY_A1=0
offX_A0=0
offY_A0=0
offX_A=0
offY_A=0
offX_B=0
offY_B=0
offX_C=0
offY_C=0
offX_D=0
offY_D=0
offX_E=0
offY_E=0
RptD_X=0
RptD_Y=100
RptLab=1
SimCmd=
UseNetN=0
LabSize=60
[eeschema/libraries]
LibName1=power
LibName2=device
LibName3=transistors
LibName4=conn
LibName5=linear
LibName6=regul
LibName7=74xx
LibName8=cmos4000
LibName9=adc-dac
LibName10=memory
LibName11=xilinx
LibName12=special
LibName13=microcontrollers
LibName14=dsp
LibName15=microchip
LibName16=analog_switches
LibName17=motorola
LibName18=texas
LibName19=intel
LibName20=audio
LibName21=interface
LibName22=digital-audio
LibName23=philips
LibName24=display
LibName25=cypress
LibName26=siliconi
LibName27=opto
LibName28=atmel
LibName29=contrib
LibName30=valves
[general]
version=1
[pcbnew]
version=1
PadDrlX=320
PadDimH=600
PadDimV=600
BoardThickness=630
TxtPcbV=800
TxtPcbH=600
TxtModV=600
TxtModH=600
TxtModW=120
VEgarde=100
DrawLar=150
EdgeLar=150
TxtLar=120
MSegLar=150
LastNetListRead=
[pcbnew/libraries]
LibDir=
LibName1=sockets
LibName2=connect
LibName3=discret
LibName4=pin_array
LibName5=divers
LibName6=libcms
LibName7=display
LibName8=valves
LibName9=led
LibName10=dip_sockets

View File

@ -0,0 +1,90 @@
EESchema Schematic File Version 2 date 19/12/2011 12:55:30
LIBS:power
LIBS:device
LIBS:transistors
LIBS:conn
LIBS:linear
LIBS:regul
LIBS:74xx
LIBS:cmos4000
LIBS:adc-dac
LIBS:memory
LIBS:xilinx
LIBS:special
LIBS:microcontrollers
LIBS:dsp
LIBS:microchip
LIBS:analog_switches
LIBS:motorola
LIBS:texas
LIBS:intel
LIBS:audio
LIBS:interface
LIBS:digital-audio
LIBS:philips
LIBS:display
LIBS:cypress
LIBS:siliconi
LIBS:opto
LIBS:atmel
LIBS:contrib
LIBS:valves
EELAYER 25 0
EELAYER END
$Descr A4 11700 8267
encoding utf-8
Sheet 1 1
Title ""
Date "19 dec 2011"
Rev ""
Comp ""
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Wire Wire Line
4150 1750 3750 1750
Wire Wire Line
4150 1450 3750 1450
Text Label 3850 1450 0 60 ~ 0
NET1
$Comp
L CONN_1 P4
U 1 1 4EE5056D
P 4300 1450
F 0 "P4" H 4380 1450 40 0000 L CNN
F 1 "CONN_1" H 4300 1505 30 0001 C CNN
1 4300 1450
1 0 0 -1
$EndComp
$Comp
L CONN_1 P3
U 1 1 4EE5056C
P 3600 1450
F 0 "P3" H 3680 1450 40 0000 L CNN
F 1 "CONN_1" H 3600 1505 30 0001 C CNN
1 3600 1450
-1 0 0 1
$EndComp
$Comp
L CONN_1 P1
U 1 1 4EDF7CC5
P 3600 1750
F 0 "P1" H 3680 1750 40 0000 L CNN
F 1 "CONN_1" H 3600 1805 30 0001 C CNN
1 3600 1750
-1 0 0 1
$EndComp
$Comp
L CONN_1 P2
U 1 1 4EDF7CC0
P 4300 1750
F 0 "P2" H 4380 1750 40 0000 L CNN
F 1 "CONN_1" H 4300 1805 30 0001 C CNN
1 4300 1750
1 0 0 -1
$EndComp
Text Label 3850 1750 0 60 ~ 0
NET2
$EndSCHEMATC

View File

@ -129,10 +129,9 @@ public:
* Function BuildTracksCandidatesList
* Fills m_Candidates with all connecting points (track ends or via location)
* with tracks from aBegin to aEnd.
* if aBegin == NULL, use first track in brd list
* if aEnd == NULL, uses all tracks from aBegin in brd list
* if aEnd == NULL, uses all tracks from aBegin
*/
void BuildTracksCandidatesList( TRACK * aBegin = NULL, TRACK * aEnd = NULL);
void BuildTracksCandidatesList( TRACK * aBegin, TRACK * aEnd = NULL);
/**
* Function BuildPadsCandidatesList
@ -209,15 +208,15 @@ public:
private:
/**
* function searchEntryPoint
* function searchEntryPointInCandidatesList
* Search an item in m_Connected connected to aPoint
* note m_Connected containts usually more than one candidate
* and searchEntryPoint returns an index to one of these candidates
* and searchEntryPointInCandidatesList returns an index to one of these candidates
* Others are neightbor of the indexed item.
* @param aPoint is the reference coordinates
* @return the index of item found or -1 if no candidate
*/
int searchEntryPoint( const wxPoint & aPoint);
int searchEntryPointInCandidatesList( const wxPoint & aPoint);
/**
* Function Merge_SubNets
@ -438,10 +437,10 @@ void CONNECTIONS::BuildTracksCandidatesList( TRACK * aBegin, TRACK * aEnd)
{
m_candidates.clear();
if( aBegin == NULL )
aBegin = m_brd->m_Track;
// if( aBegin == NULL )
// aBegin = m_brd->m_Track;
m_firstTrack = aBegin;
m_firstTrack = m_lastTrack = aBegin;
unsigned ii = 0;
// Count candidates ( i.e. end points )
@ -489,7 +488,7 @@ int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack )
wxPoint position = aTrack->m_Start;
for( int kk = 0; kk < 2; kk++ )
{
int idx = searchEntryPoint( position );
int idx = searchEntryPointInCandidatesList( position );
if ( idx >= 0 )
{
// search after:
@ -524,7 +523,7 @@ int CONNECTIONS::SearchConnectedTracks( const TRACK * aTrack )
return count;
}
int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint)
int CONNECTIONS::searchEntryPointInCandidatesList( const wxPoint & aPoint)
{
// Search the aPoint coordinates in m_Candidates
// m_Candidates is sorted by X then Y values, and a fast binary search is used
@ -582,6 +581,7 @@ int CONNECTIONS::searchEntryPoint( const wxPoint & aPoint)
/* Used after a track change (delete a track ou add a track)
* Connections to pads are recalculated
* Note also aFirstTrack (and aLastTrack ) can be NULL
*/
void CONNECTIONS::Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK* aLastTrack, int aNetcode )
{
@ -611,6 +611,9 @@ void CONNECTIONS::Build_CurrNet_SubNets_Connections( TRACK* aFirstTrack, TRACK*
BuildPadsList( aNetcode );
SearchTracksConnectedToPads();
// Update connections between intersecting pads (no tracks)
SearchConnectionsPadsToIntersectingPads();
// Creates sub nets (clusters) for the current net:
Propagate_SubNets();
}
@ -705,13 +708,54 @@ int CONNECTIONS::Merge_SubNets( int aOldSubNet, int aNewSubNet )
*/
void CONNECTIONS::Propagate_SubNets()
{
TRACK* curr_track;
int sub_netcode;
int sub_netcode = 0;
curr_track = (TRACK*)m_firstTrack;
sub_netcode = 1;
curr_track->SetSubNet( sub_netcode );
// Examine connections between intersecting pads
for( unsigned ii = 0; ii < m_sortedPads.size(); ii++ )
{
D_PAD * curr_pad = m_sortedPads[ii];
for( unsigned jj = 0; jj < curr_pad->m_PadsConnected.size(); jj++ )
{
D_PAD * pad = curr_pad->m_PadsConnected[jj];
if( curr_pad->GetSubNet() )
{
if( pad->GetSubNet() > 0 )
{
// The pad is already a cluster member, so we can merge the 2 clusters
Merge_PadsSubNets( pad->GetSubNet(), curr_pad->GetSubNet() );
}
else
{
// The pad is not yet attached to a cluster,
// so we can add this pad to the cluster
pad->SetSubNet( curr_pad->GetSubNet() );
}
}
else /* the track segment is not attached to a cluster */
{
if( pad->GetSubNet() > 0 )
{
// it is connected to a pad in a cluster, merge this pad
curr_pad->SetSubNet( pad->GetSubNet() );
}
else
{
// it is connected to a pad not in a cluster,
// so we must create a new cluster (only with the 2 pads.
sub_netcode++;
curr_pad->SetSubNet( sub_netcode );
pad->SetSubNet( curr_pad->GetSubNet() );
}
}
}
}
sub_netcode++;
TRACK* curr_track = (TRACK*)m_firstTrack;
if( curr_track )
curr_track->SetSubNet( sub_netcode );
// Examine connections between trcaks and pads
for( ; curr_track != NULL; curr_track = curr_track->Next() )
{
/* First: handling connections to pads */
@ -793,6 +837,12 @@ void CONNECTIONS::Propagate_SubNets()
}
}
/*
* Test all connections of the board,
* and update subnet variable of pads and tracks
* TestForActiveLinksInRatsnest must be called after this function
* to update active/inactive ratsnest items status
*/
void PCB_BASE_FRAME::TestConnections()
{
// Clear the cluster identifier for all pads
@ -806,21 +856,41 @@ void PCB_BASE_FRAME::TestConnections()
m_Pcb->Test_Connections_To_Copper_Areas();
// int st = clock(); // For test only, will be removed
// Test existing connections net by net
// note some nets can have no tracks, and pads intersecting
// so Build_CurrNet_SubNets_Connections must be called for each net
CONNECTIONS connections( m_Pcb );
int last_net_tested = 0;
int current_net_code = 0;
for( TRACK* track = m_Pcb->m_Track; track; )
{
// At this point, track is the first track of a given net
int current_net_code = track->GetNet();
current_net_code = track->GetNet();
// Get last track of the current net
TRACK* lastTrack = track->GetEndNetCode( current_net_code );
if( current_net_code > 0 ) // do not spend time if net code = 0 ( dummy net )
{
// Test all previous nets having no tracks
for( int net = last_net_tested+1; net < current_net_code; net++ )
connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net );
connections.Build_CurrNet_SubNets_Connections( track, lastTrack, current_net_code );
last_net_tested = current_net_code;
}
track = lastTrack->Next(); // this is now the first track of the next net
}
// Test last nets without tracks, if any
int netsCount = m_Pcb->GetNetCount();
for( int net = last_net_tested+1; net < netsCount; net++ )
connections.Build_CurrNet_SubNets_Connections( NULL, NULL, net );
// wxLogMessage("time %g ms", (double)(clock() - st)*1000.0/CLOCKS_PER_SEC);
Merge_SubNets_Connected_By_CopperAreas( m_Pcb );
return;
@ -925,7 +995,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
CONNECTIONS connections( m_Pcb );
connections.BuildPadsList();
connections.BuildTracksCandidatesList();
connections.BuildTracksCandidatesList(m_Pcb->m_Track);
// First pass: build connections between track segments and pads.
connections.SearchTracksConnectedToPads();