Commit 387a8763 authored by CHARRAS's avatar CHARRAS
Browse files

Removed enhancements in connectivity computation (in certain cases, does not work)

parent 0d403649
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -4,6 +4,17 @@ Started 2007-June-11
Please add newer entries at the top, list the date and your name with 
email address.

2007-Oct-17 UPDATE  Jean-Pierre Charras <jean-pierre.charras@inpg.fr>
================================================================================
+ pcbnew:
	Removed enhancements in connectivity computation because
	rastnest computation does not work (errors) with short track segments
	(lenght < width) . This is not a bug, but an algorithm problem, so
	I must work on algos.
	
	


2007-Oct-17 UPDATE   Geoff Harland <gharlandau@yahoo.com.au>
================================================================================
+ pcbnew
+0 −1
Original line number Diff line number Diff line
@@ -502,7 +502,6 @@ public:
    int*            build_ratsnest_pad( EDA_BaseStruct* ref, const wxPoint& refpos, bool init );

    void            Tst_Ratsnest( wxDC* DC, int ref_netcode );
    void            Recalcule_all_net_connexion( wxDC* DC );
    void            test_connexions( wxDC* DC );
    void            test_1_net_connexion( wxDC* DC, int net_code );
    void            reattribution_reference_piste( int affiche );
+26 −0
Original line number Diff line number Diff line
@@ -16,6 +16,28 @@
#include "protos.h"


// #define RATSNET_DEBUG

#ifdef RATSNET_DEBUG

/**************************************/
void DbgDisplayTrackInfos(TRACK * track)
/**************************************/
/* Only for ratsnest debug
*/
{
wxString msg;
	msg << wxT("Netcode ") << track->GetNet();
	msg << wxT(" - ") << track->GetSubNet();
	msg << wxT("\nptrS ") << (unsigned) track->start;
	msg << wxT(" ptrE ") << (unsigned) track->end;
	msg << wxT(" this ") << (unsigned) track;
	
	wxMessageBox(msg);
}

#endif

/**************************************/
/* Classes pour Pistes, Vias et Zones */
/**************************************/
@@ -715,6 +737,9 @@ void TRACK::Display_Infos( WinEDA_DrawFrame* frame )
{
    wxString msg;
    int      text_pos;
#ifdef RATSNET_DEBUG
DbgDisplayTrackInfos(this);
#endif

    frame->MsgPanel->EraseMsgBox();

@@ -865,6 +890,7 @@ bool TRACK::HitTest( const wxPoint& ref_pos )
}



#if defined(DEBUG)

/**
+127 −154
Original line number Diff line number Diff line
@@ -15,14 +15,11 @@

/* variables locales */

/* routines exportees */
void        Recalcule_all_net_connexion( wxDC* DC );

/* Routines locales */
static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn );
static void RebuildTrackChain( BOARD* pcb );
static int  tri_par_netcode( TRACK** pt_ref, TRACK** pt_compare );
static int  Sort_By_NetCode( TRACK** pt_ref, TRACK** pt_compare );

/*..*/

@@ -101,7 +98,7 @@ static void propage_equipot( TRACK* pt_start_conn, TRACK* pt_end_conn )
    TRACK*      pt_autre_piste;
    BOARD_ITEM* PtStruct;

    /* Initialisations prealables */
    /* Clear variables used in computations */
    pt_conn = pt_start_conn;
    for( ; pt_conn != NULL; pt_conn = (TRACK*) pt_conn->Pnext )
    {
@@ -304,38 +301,6 @@ void WinEDA_BasePcbFrame::test_connexions( wxDC* DC )
}


/**************************************************************/
void WinEDA_BasePcbFrame::Recalcule_all_net_connexion( wxDC* DC )
/**************************************************************/

/*
 *  Routine Recalculant les pointeurs sur connexions types piste a piste
 *  relatives a tous les nets.
 *  Cette routine est utilisee apres reclassement des segments de piste par
 *  ordre de net_code, puisque des pointeurs sur connexions deviennent faux
 *  ( les pointeurs type pad restent bons )
 */
{
    TRACK* EndConn;
    int    net_code, net_code_max;

    if( m_Pcb->m_Track == NULL )
        return;

    /* calcul du net_code max */
    EndConn = m_Pcb->m_Track;
    while( EndConn->Pnext )
        EndConn = (TRACK*) EndConn->Pnext;

    net_code_max = EndConn->GetNet();

    for( net_code = 0; net_code <= net_code_max; net_code++ )
    {
        test_1_net_connexion( DC, net_code );
    }
}


/*************************************************************************/
void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
/*************************************************************************/
@@ -396,26 +361,25 @@ void WinEDA_BasePcbFrame::test_1_net_connexion( wxDC* DC, int net_code )
}


bool zflg;	// DEBUG, must be removed

/***************************************************************************/
static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
/***************************************************************************/

/* calcule la connexite d'un net constitue de segments de piste consecutifs.
 *  Entree:
 *      pt_start_conn = adresse du 1er segment ( debut du net )
 *      pt_end_conn = adr de fin (dernier segment)
 *  Les connexions relatives aux pads doivent etre deja calculees, car elles
 *  ne sont pas ici recalculees ( pour des raisons de temps de calcul, et
 *  du fait que lors des modif de pistes, les pads ne sont pas touches
/**  Used after a track change (delete a track ou add a track)
 * Compute connections (initialize the .start and .end members) for a single net.
 * tracks must be sorted by net, as usual
 *  @param pt_start_conn = first segment of the net
 *  @param pt_end_conn = last segment of the net
 *  Connections to pads are assumed to be already initialized.
 *  If a track is deleted, the other pointers to pads do not change.
 *  When a track is added, its pointers to pads are already initialized
 */
{
    TRACK* Track;

    /*  Les pointeurs .start et .end sont mis a jour, si la
     *   connexion est du type segment a segment.
     *  la connexion sur pads est supposee etre deja calculee */

    /* Raz des pointeurs sur pistes */
    /* Reset the old connections type track to track */
    for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext )
    {
        Track->SetSubNet( 0 );
@@ -430,10 +394,10 @@ static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
            break;
    }

    /* calcul des connexions */
    /* Update connections type track to track */
    for( Track = pt_start_conn; Track != NULL; Track = (TRACK*) Track->Pnext )
    {
        if( Track->Type() == TYPEVIA )
        if( Track->Type() == TYPEVIA )	// A via can connect many tracks, we must search for all track segments in this net
        {
            TRACK* pt_segm;
            int    layermask = Track->ReturnMaskLayer();
@@ -457,42 +421,33 @@ static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
            }
        }

        if( Track->start == NULL )
		zflg = false;

        if( Track->start == NULL )	// end track not already connected, search a connection
        {
            Track->start = Locate_Piste_Connectee( Track, Track, pt_end_conn, START );
            Track->start = Locate_Piste_Connectee( Track, pt_start_conn /*Track*/, pt_end_conn, START );
        }

        if( Track->end == NULL )
        if( Track->end == NULL )	// end track not already connected, search a connection
        {
            Track->end = Locate_Piste_Connectee( Track, Track, pt_end_conn, END );
            Track->end = Locate_Piste_Connectee( Track, pt_start_conn/*Track*/, pt_end_conn, END );
        }
        if( Track == pt_end_conn )
            break;
    }
		zflg = false;

    /* Generation des sous equipots du net */
    propage_equipot( pt_start_conn, pt_end_conn );
}


/********************************************/
/* Reattribution des net_codes de reference */
/********************************************/

/*
 *  reattribution des net_codes aux segments de pistes.
 *  Routine utilisee apres modification generale des noms de nets (apres
 *  lecrure netliste ou edition de nets sur pads, effacement /ajout de
 *  modules...)
 * 
 *  Elle se fait en 2 passes:
 *      1 - reattribution des segments commencant ( et/ou finissant ) sur 1 pad
 *          les autres segments sont mis a reference NULLE
 *      2 - reattribution des segments restantes a ref NULLE
 */

#define POS_AFF_CHREF 62

/******************************************************************************/
static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* pcb, LISTE_PAD* pt_liste,
                                             int px, int py, int masque_layer )
/******************************************************************************/
/* recherche le pad connecte a l'extremite de la piste de coord px, py
 *  parametres d'appel:
 *      px, py = coord du point tst
@@ -507,9 +462,6 @@ static void calcule_connexite_1_net( TRACK* pt_start_conn, TRACK* pt_end_conn )
 *
 *  (la liste placee en m_Pcb->m_Pads et elle triee par netcodes croissants)
 */

static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* pcb, LISTE_PAD* pt_liste,
                                             int px, int py, int masque_layer )
{
    D_PAD*     pad;
    LISTE_PAD* ptr_pad, * lim;
@@ -608,9 +560,16 @@ LISTE_PAD* CreateSortedPadListByXCoord( BOARD* pcb )
}


/******************************************************************/
/********************************************************************/
void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
/******************************************************************/
/********************************************************************/

/* search connections between tracks and pads, and propagate pad net codes to the track segments
  * This is a 2 pass computation.
  * The pad netcodes are assumed to be initialized.
  * First:
  * We search a connection between a track segment and a pad: if found : this segment  netcode is set to the pad netcode
 */
{
    TRACK*      pt_piste,
    * pt_next;
@@ -634,29 +593,32 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
    if( affiche )
        Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Gen Pads " ), a_color );

    //////////////////////////////////////////////////////
    // Connexion des pistes accrochees a 1 pad au moins //
    //////////////////////////////////////////////////////
    /**************************************************************/
    /* Pass 1: search the connections between track ends and pads */
    /**************************************************************/
    pt_mem = CreateSortedPadListByXCoord( m_Pcb );

    if( affiche )
        Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Conn Pads" ), a_color );

    /* Raz des flags particuliers des segments de piste */
    /* Reset variables and flags used in computation */
    pt_piste = m_Pcb->m_Track;
    for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext )
    {
        pt_piste->SetState( BUSY | EDIT | BEGIN_ONPAD | END_ONPAD, OFF );
        pt_piste->SetNet( 0 );
        pt_piste->SetNet( 0 );  // net code = 0 means not connected
    }

    /* First pass: search connection between a track segment and a pad.
      * if found, set the track net code to the pad netcode
     */
    pt_piste = m_Pcb->m_Track;
    for( ; pt_piste != NULL; pt_piste = (TRACK*) pt_piste->Pnext )
    {
        flag = 0;
        masque_layer = g_TabOneLayerMask[pt_piste->GetLayer()];

        /* y a t-il une pastille sur une extremite */
        /* Search for a pad on the segment starting point */
        pt_piste->start = SuperFast_Locate_Pad_Connecte( m_Pcb,
                                                         pt_mem,
                                                         pt_piste->m_Start.x,
@@ -668,6 +630,7 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
            pt_piste->SetNet( ( (D_PAD*) (pt_piste->start) )->GetNet() );
        }

        /* Search for a pad on the segment ending point */
        pt_piste->end = SuperFast_Locate_Pad_Connecte( m_Pcb,
                                                       pt_mem,
                                                       pt_piste->m_End.x,
@@ -683,12 +646,14 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )

    MyFree( pt_mem );

    ////////////////////////////////////////////////////
    // Calcul de la connexite entre segments de piste //
    ////////////////////////////////////////////////////
    /*****************************************************/
    /* Pass 2: search the connections between track ends */
    /*****************************************************/

    /*  Les pointeurs .start et .end sont mis a jour, s'ils etaient NULLs.
     *  La connexion est alors du type segment a segment
    /*  the .start et .end member pointers are updated, only if NULLs
     * (if not nuls, the end is already connected to a pad).
     * the connection (if found) is between segments
	 * when a track has a net code and the other has a null net code, the null net code is changed
     */
    if( affiche )
        Affiche_1_Parametre( this, POS_AFF_CHREF, wxEmptyString, wxT( "Conn Segm" ), a_color );
@@ -706,9 +671,9 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
        }
    }

    ////////////////////////////////
    // Reattribution des net_code //
    ////////////////////////////////
    /**********************************************************/
    /* Propagate net codes from a segment to an other segment */
    /**********************************************************/

    a_color = YELLOW;

@@ -751,9 +716,16 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
                pt_piste->SetState( BUSY, OFF );
            }

        /* set the netcode of connected tracks: if at track is connected to a pad, its net code is already set.
         * if the current track is connected to an other track:
         * if a track has a net code, it is used for the other track.
         * Thus there is a propagation of the netcode from a track to an other.
         * if none of the 2 track has a net code we do nothing
         * the iteration is stopped when no new change occurs
         */
        for( pt_piste = m_Pcb->m_Track; pt_piste != NULL; pt_piste = pt_piste->Next() )
        {
            /* Traitement du point de debut */
            /* look for the connection to the current segment starting point */
            PtStruct = (BOARD_ITEM*) pt_piste->start;
            if( PtStruct && (PtStruct->Type() != TYPEPAD) )
            {
@@ -761,15 +733,15 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
                pt_next = (TRACK*) PtStruct;
                if( pt_piste->GetNet() )
                {
                    if( pt_next->GetNet() == 0 )
                    if( pt_next->GetNet() == 0 )    // the current track has a netcode, we use it for the other track
                    {
                        new_passe_request  = 1;
                        new_passe_request = 1;      // A change is made: a new iteration is requested.
                        pt_next->SetNet( pt_piste->GetNet() );
                    }
                }
                else
                {
                    if( pt_next->GetNet() != 0 )
                    if( pt_next->GetNet() != 0 )    // the other track has a netcode, we use it for the current track
                    {
                        pt_piste->SetNet( pt_next->GetNet() );
                        new_passe_request = 1;
@@ -777,12 +749,13 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
                }
            }

            /* Localisation du point de fin */
            /* look for the connection to the current segment ending point */
            PtStruct = pt_piste->end;
            if( PtStruct &&(PtStruct->Type() != TYPEPAD) )
            {
                // End sur piste
                pt_next = (TRACK*) PtStruct;

                // End on an other track: propagate netcode if possible
                if( pt_piste->GetNet() )
                {
                    if( pt_next->GetNet() == 0 )
@@ -803,7 +776,7 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
        }
    }

    /* Reclassemment des pistes par numero de net: */
    /* Sort the track list by net codes: */
    if( affiche )
        Affiche_1_Parametre( this, -1, wxEmptyString, wxT( "Reorder " ), a_color );
    RebuildTrackChain( m_Pcb );
@@ -817,7 +790,7 @@ void WinEDA_BasePcbFrame::reattribution_reference_piste( int affiche )
 *  routine de tri de connexion utilisee par la fonction QSORT
 *  le tri est fait par numero de net
 */
int tri_par_netcode( TRACK** pt_ref, TRACK** pt_compare )
int Sort_By_NetCode( TRACK** pt_ref, TRACK** pt_compare )
{
    int ii;

@@ -851,7 +824,7 @@ static void RebuildTrackChain( BOARD* pcb )
    }

    qsort( Liste, nbsegm, sizeof(TRACK*),
           ( int( * ) ( const void*, const void* ) )tri_par_netcode );
           ( int( * ) ( const void*, const void* ) )Sort_By_NetCode );

    /* Update the linked list pointers */

+42 −27
Original line number Diff line number Diff line
@@ -664,18 +664,27 @@ TEXTE_MODULE* LocateTexteModule( BOARD* Pcb, MODULE** PtModule, int typeloc )



/******************************************/
inline int Dist(wxPoint & p1, wxPoint & p2)
/******************************************/
/******************************************************************/
inline bool IsPointsAreNear(wxPoint & p1, wxPoint & p2, int max_dist)
/******************************************************************/
/*
return the dist min between p1 and p2
return true if the dist between p1 and p2 < max_dist
Currently in test (currently rasnest algos work only if p1 == p2
*/
{
extern bool zflg;
if (zflg == true)
{
int dist;
	dist = abs(p1.x - p2.x) + abs (p1.y - p2.y);
	dist *= 7;
	dist /= 10;
	return dist;
	if ( dist < max_dist ) return true;
}
else
	if ( p1 == p2 ) return true;
//#endif
	return false;
}

/**************************************************************/
@@ -683,25 +692,30 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
                               TRACK* pt_lim, int extr )
/**************************************************************/

/* recherche le segment connecte au segment pointe par
 *  PtRefSegm:
 *  si int extr = START, le point de debut du segment est utilise
 *  si int extr = END, le point de fin du segment est utilise
 *  La recherche ne se fait que sur les EXTREMITES des segments
/** Search for the track (or via) segment which is connected to the track segment PtRefSegm
 *  if extr == START, the starting track segment PtRefSegm is used to locate a connected segment
 *  if extr == END, the ending track segment PtRefSegm is used
 *  The test connection consider only end track segments
 * 
 *  Search is made from  pt_base to pt_lim (in the track linked list)
 *  if pt_lim == NULL,  the search  is made from  pt_base to the end of list
 *
 *  In order to have a fast computation time:
 *  a first search is made considering only the +/- 50 next door neightbour of PtRefSegm.
 *  if no track is found : the entire list is tested
 *
 *  La recherche se fait de l'adresse :
 *      pt_base a pt_lim (borne finale comprise)
 *      si pt_lim = NULL, la recherche se fait jusqu'a la fin de la liste
 *  Afin d'accelerer la recherche, une 1ere passe est faite, avec une recherche
 *  realisee sur un ensemble de +/- 100 points autour du point courant.
 *  Si echec: recherche generale
 *  @param PtRefSegm = reference segment
 *  @param pt_base = lower limit for search
 *  @param pt_lim = upper limit for search (can be NULL)
 *  @param extr = START or END = end of ref track segment to use in tests
 */
{
	#define NEIGHTBOUR_COUNT_MAX 50
    TRACK*  PtSegmB, * PtSegmN;
    int     Reflayer;
    wxPoint pos_ref;
    int     ii;
	int     min_dist;
	int     max_dist;

    if( extr == START )
        pos_ref = PtRefSegm->m_Start;
@@ -713,7 +727,7 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
    /* 1ere passe */
    PtSegmB = PtSegmN = PtRefSegm;

    for( ii = 0; ii < 50; ii++ )
    for( ii = 0; ii < NEIGHTBOUR_COUNT_MAX; ii++ )
    {
        if( (PtSegmN == NULL) && (PtSegmB == NULL) )
            break;
@@ -725,15 +739,16 @@ TRACK* Locate_Piste_Connectee( TRACK* PtRefSegm, TRACK* pt_base,
            if( PtSegmN == PtRefSegm )
                goto suite;

			min_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2;
			/* max_dist is the max distance between 2 tack ends which ensure a copper continuty */
			max_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2;

            if( Dist(pos_ref, PtSegmN->m_Start) < min_dist )
            if( IsPointsAreNear(pos_ref, PtSegmN->m_Start, max_dist) )
            {       /* Test des couches */
                if( Reflayer & PtSegmN->ReturnMaskLayer() )
                    return PtSegmN;
            }

            if( Dist(pos_ref, PtSegmN->m_End) < min_dist )
            if( IsPointsAreNear(pos_ref, PtSegmN->m_End, max_dist) )
            {       /* Test des couches */
                if( Reflayer & PtSegmN->ReturnMaskLayer() )
                    return PtSegmN;
@@ -752,15 +767,15 @@ suite:
            if( PtSegmB == PtRefSegm )
                goto suite1;

			min_dist = (PtSegmB->m_Width + PtRefSegm->m_Width)/2;
			max_dist = (PtSegmB->m_Width + PtRefSegm->m_Width)/2;

            if( Dist(pos_ref, PtSegmB->m_Start) < min_dist )
            if( IsPointsAreNear(pos_ref, PtSegmB->m_Start, max_dist) )
            {       /* Test des couches */
                if( Reflayer & PtSegmB->ReturnMaskLayer() )
                    return PtSegmB;
            }

            if( Dist(pos_ref, PtSegmB->m_End) < min_dist )
            if( IsPointsAreNear(pos_ref, PtSegmB->m_End, max_dist) )
            {       /* Test des couches */
                if( Reflayer & PtSegmB->ReturnMaskLayer() )
                    return PtSegmB;
@@ -792,15 +807,15 @@ suite1:
        }


		min_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2;
		max_dist = (PtSegmN->m_Width + PtRefSegm->m_Width)/2;

        if( Dist(pos_ref,PtSegmN->m_Start) < min_dist )
        if( IsPointsAreNear(pos_ref,PtSegmN->m_Start, max_dist) )
        {       /* Test des couches */
            if( Reflayer & PtSegmN->ReturnMaskLayer() )
                return PtSegmN;
        }

        if( Dist(pos_ref, PtSegmN->m_End) < min_dist )
        if( IsPointsAreNear(pos_ref, PtSegmN->m_End, max_dist) )
        {       /* Test des couches */
            if( Reflayer & PtSegmN->ReturnMaskLayer() )
                return PtSegmN;