kicad/pcbnew/work.cpp

211 lines
4.8 KiB
C++

/************************/
/* Autorouting routines */
/************************/
#include "fctsys.h"
#include "common.h"
#include "pcbnew.h"
#include "autorout.h"
#include "cell.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;
MyFree( 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*) MyMalloc( sizeof(CWORK) ) ) != 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 );
}