248 lines
6.1 KiB
C++
248 lines
6.1 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
|
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
|
* Copyright (C) 1992-2011 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
|
|
* 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
|
|
*/
|
|
|
|
/**
|
|
* @file work.cpp
|
|
* @brief Automatic routing routines
|
|
*/
|
|
|
|
#include "fctsys.h"
|
|
#include "common.h"
|
|
|
|
#include "pcbnew.h"
|
|
#include "cell.h"
|
|
#include "ar_protos.h"
|
|
|
|
|
|
struct CWORK /* a unit of work is a hole-pair to connect */
|
|
{
|
|
struct CWORK* Next;
|
|
int FromRow; /* source row */
|
|
int FromCol; /* source column */
|
|
int net_code; /* net_code */
|
|
int ToRow; /* target row */
|
|
int ToCol; /* target column */
|
|
RATSNEST_ITEM* pt_rats; /* Corresponding ratsnest */
|
|
int ApxDist; /* approximate distance */
|
|
int Cost; /* cost for sort by length */
|
|
int Priority; /* route priority */
|
|
};
|
|
|
|
|
|
/* pointers to the first and last item of work to do */
|
|
static CWORK* Head = NULL;
|
|
static CWORK* Tail = NULL;
|
|
static CWORK* Current = NULL;
|
|
|
|
|
|
void InitWork();
|
|
void ReInitWork();
|
|
int SetWork( int, int, int, int, int, RATSNEST_ITEM*, int );
|
|
void GetWork( int*, int*, int*, int*, int*, RATSNEST_ITEM** );
|
|
void SortWork();
|
|
|
|
|
|
/* initialize the work list */
|
|
void InitWork()
|
|
{
|
|
CWORK* ptr;
|
|
|
|
while( ( ptr = Head ) != NULL )
|
|
{
|
|
Head = ptr->Next;
|
|
delete ptr;
|
|
}
|
|
|
|
Tail = Current = NULL;
|
|
}
|
|
|
|
|
|
/* initialize the work list */
|
|
void ReInitWork()
|
|
{
|
|
Current = Head;
|
|
}
|
|
|
|
|
|
/* add a unit of work to the work list
|
|
* Return:
|
|
* 1 if OK
|
|
* 0 if memory allocation failed
|
|
*/
|
|
static int GetCost( int r1, int c1, int r2, int c2 );
|
|
|
|
int SetWork( int r1,
|
|
int c1,
|
|
int n_c,
|
|
int r2,
|
|
int c2,
|
|
RATSNEST_ITEM* pt_ch,
|
|
int pri )
|
|
{
|
|
CWORK* p;
|
|
|
|
if( ( p = (CWORK*) operator new( sizeof(CWORK), std::nothrow ) ) != NULL )
|
|
{
|
|
p->FromRow = r1;
|
|
p->FromCol = c1;
|
|
p->net_code = n_c;
|
|
p->ToRow = r2;
|
|
p->ToCol = c2;
|
|
p->pt_rats = pt_ch;
|
|
p->ApxDist = GetApxDist( r1, c1, r2, c2 );
|
|
p->Cost = GetCost( r1, c1, r2, c2 );
|
|
p->Priority = pri;
|
|
p->Next = NULL;
|
|
|
|
if( Head ) /* attach at end */
|
|
|
|
Tail->Next = p;
|
|
else /* first in list */
|
|
Head = Current = p;
|
|
|
|
Tail = p;
|
|
return 1;
|
|
}
|
|
else /* can't get any more memory */
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* fetch a unit of work from the work list */
|
|
void GetWork( int* r1,
|
|
int* c1,
|
|
int* n_c,
|
|
int* r2,
|
|
int* c2,
|
|
RATSNEST_ITEM** pt_ch )
|
|
{
|
|
if( Current )
|
|
{
|
|
*r1 = Current->FromRow;
|
|
*c1 = Current->FromCol;
|
|
*n_c = Current->net_code;
|
|
*r2 = Current->ToRow;
|
|
*c2 = Current->ToCol;
|
|
*pt_ch = Current->pt_rats;
|
|
Current = Current->Next;
|
|
}
|
|
else /* none left */
|
|
{
|
|
*r1 = *c1 = *r2 = *c2 = ILLEGAL;
|
|
*n_c = 0;
|
|
*pt_ch = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/* order the work items; shortest (low cost) first */
|
|
void SortWork()
|
|
{
|
|
CWORK* p;
|
|
CWORK* q0; /* put PRIORITY PAD_CONNECTs in q0 */
|
|
CWORK* q1; /* sort other PAD_CONNECTs in q1 */
|
|
CWORK* r;
|
|
|
|
q0 = q1 = NULL;
|
|
|
|
while( (p = Head) != NULL ) /* prioritize each work item */
|
|
{
|
|
Head = Head->Next;
|
|
|
|
if( p->Priority ) /* put at end of priority list */
|
|
{
|
|
p->Next = NULL;
|
|
|
|
if( (r = q0) == NULL ) /* empty list? */
|
|
{
|
|
q0 = p;
|
|
}
|
|
else /* attach at end */
|
|
{
|
|
while( r->Next ) /* search for end */
|
|
r = r->Next;
|
|
|
|
r->Next = p; /* attach */
|
|
}
|
|
}
|
|
else if( ( ( r = q1 ) == NULL ) || ( p->Cost < q1->Cost ) )
|
|
{
|
|
p->Next = q1;
|
|
q1 = p;
|
|
}
|
|
else /* find proper position in list */
|
|
{
|
|
while( r->Next && p->Cost >= r->Next->Cost )
|
|
r = r->Next;
|
|
|
|
p->Next = r->Next;
|
|
r->Next = p;
|
|
}
|
|
}
|
|
|
|
if( (p = q0) != NULL ) /* any priority PAD_CONNECTs? */
|
|
{
|
|
while( q0->Next )
|
|
q0 = q0->Next;
|
|
|
|
q0->Next = q1;
|
|
}
|
|
else
|
|
p = q1;
|
|
|
|
/* reposition Head and Tail */
|
|
for( Head = Current = Tail = p; Tail && Tail->Next; Tail = Tail->Next )
|
|
;
|
|
}
|
|
|
|
|
|
/* Calculate the cost of a net:
|
|
* cost = (| dx | + | dy |) * disability
|
|
* disability = 1 if dx or dy = 0, max if | dx | # | dy |
|
|
*/
|
|
static int GetCost( int r1, int c1, int r2, int c2 )
|
|
{
|
|
int dx, dy, mx, my;
|
|
float incl;
|
|
|
|
dx = abs( c2 - c1 );
|
|
dy = abs( r2 - r1 );
|
|
incl = 1.0;
|
|
mx = dx;
|
|
my = dy;
|
|
|
|
if( mx < my )
|
|
{
|
|
mx = dy; my = dx;
|
|
}
|
|
|
|
if( mx )
|
|
incl += (2 * (float) my / mx);
|
|
|
|
return (int) ( ( dx + dy ) * incl );
|
|
}
|