Uncrustifying push&shove router

This commit is contained in:
Maciej Sumiński 2013-09-26 23:53:54 +02:00
parent 9bef4cb797
commit 85d1048762
37 changed files with 6255 additions and 5692 deletions

View File

@ -48,3 +48,4 @@ set(PCBNEW_PNS_SRCS
) )
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )

View File

@ -31,7 +31,6 @@
class DIRECTION_45 class DIRECTION_45
{ {
public: public:
/** /**
@ -39,7 +38,8 @@ public:
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
*/ */
enum Directions { enum Directions
{
N = 0, N = 0,
NE = 1, NE = 1,
E = 2, E = 2,
@ -55,11 +55,12 @@ public:
* Enum AngleType * Enum AngleType
* Represents kind of angle formed by vectors heading in two DIRECTION_45s. * Represents kind of angle formed by vectors heading in two DIRECTION_45s.
*/ */
enum AngleType { enum AngleType
ANG_OBTUSE = 0x1, {
ANG_RIGHT = 0x2, ANG_OBTUSE = 0x01,
ANG_ACUTE = 0x4, ANG_RIGHT = 0x02,
ANG_STRAIGHT = 0x8, ANG_ACUTE = 0x04,
ANG_STRAIGHT = 0x08,
ANG_HALF_FULL = 0x10, ANG_HALF_FULL = 0x10,
ANG_UNDEFINED = 0x20 ANG_UNDEFINED = 0x20
}; };
@ -93,16 +94,35 @@ public:
{ {
switch( m_dir ) switch( m_dir )
{ {
case N : return "north"; case N:
case NE : return "north-east"; return "north";
case E : return "east";
case SE : return "south-east"; case NE:
case S : return "south"; return "north-east";
case SW : return "south-west";
case W : return "west"; case E:
case NW : return "north-west"; return "east";
case UNDEFINED : return "undefined";
default: return "<Error>"; case SE:
return "south-east";
case S:
return "south";
case SW:
return "south-west";
case W:
return "west";
case NW:
return "north-west";
case UNDEFINED:
return "undefined";
default:
return "<Error>";
} }
} }
@ -115,6 +135,7 @@ public:
{ {
if( m_dir == UNDEFINED ) if( m_dir == UNDEFINED )
return UNDEFINED; return UNDEFINED;
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE }; const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE };
return OppositeMap[m_dir]; return OppositeMap[m_dir];
} }
@ -172,7 +193,9 @@ public:
* @param aStartDiagonal whether the first segment has to be diagonal * @param aStartDiagonal whether the first segment has to be diagonal
* @return the trace * @return the trace
*/ */
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I& aP0, const VECTOR2I &aP1, bool aStartDiagonal = false) const const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0,
const VECTOR2I& aP1,
bool aStartDiagonal = false ) const
{ {
int w = abs( aP1.x - aP0.x ); int w = abs( aP1.x - aP0.x );
int h = abs( aP1.y - aP0.y ); int h = abs( aP1.y - aP0.y );
@ -186,7 +209,9 @@ public:
{ {
mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E
mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
} else { }
else
{
mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N
mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
} }
@ -201,6 +226,7 @@ public:
SHAPE_LINE_CHAIN pl; SHAPE_LINE_CHAIN pl;
pl.Append( aP0 ); pl.Append( aP0 );
if( start_diagonal ) if( start_diagonal )
pl.Append( aP0 + mp1 ); pl.Append( aP0 + mp1 );
else else
@ -224,15 +250,20 @@ public:
const DIRECTION_45 Right() const const DIRECTION_45 Right() const
{ {
DIRECTION_45 r; DIRECTION_45 r;
r.m_dir = (Directions) (m_dir + 1); r.m_dir = (Directions) (m_dir + 1);
if( r.m_dir == NW ) if( r.m_dir == NW )
r.m_dir = N; r.m_dir = N;
return r; return r;
} }
private: private:
template <typename T> int sign(T val) const { template <typename T>
int sign( T val ) const
{
return (T( 0 ) < val) - ( val < T( 0 ) ); return (T( 0 ) < val) - ( val < T( 0 ) );
} }
@ -245,12 +276,15 @@ private:
void construct( const VECTOR2I& aVec ) void construct( const VECTOR2I& aVec )
{ {
m_dir = UNDEFINED; m_dir = UNDEFINED;
if( aVec.x == 0 && aVec.y == 0 ) if( aVec.x == 0 && aVec.y == 0 )
return; return;
double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0; double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
if( mag >= 360.0 ) if( mag >= 360.0 )
mag -= 360.0; mag -= 360.0;
if( mag < 0.0 ) if( mag < 0.0 )
mag += 360.0; mag += 360.0;
@ -258,10 +292,12 @@ private:
if( m_dir >= 8 ) if( m_dir >= 8 )
m_dir = (Directions)( m_dir - 8 ); m_dir = (Directions)( m_dir - 8 );
if( m_dir < 0 ) if( m_dir < 0 )
m_dir = (Directions)( m_dir + 8 ); m_dir = (Directions)( m_dir + 8 );
return; return;
if( aVec.y < 0 ) if( aVec.y < 0 )
{ {
if( aVec.x > 0 ) if( aVec.x > 0 )
@ -293,3 +329,4 @@ private:
}; };
#endif // __DIRECTION_H #endif // __DIRECTION_H

View File

@ -37,10 +37,9 @@
* overlap and improving search time. * overlap and improving search time.
**/ **/
class PNS_INDEX { class PNS_INDEX
{
public: public:
typedef std::list<PNS_ITEM*> NetItemsList; typedef std::list<PNS_ITEM*> NetItemsList;
typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex;
typedef boost::unordered_set<PNS_ITEM*> ItemSet; typedef boost::unordered_set<PNS_ITEM*> ItemSet;
@ -54,6 +53,7 @@ public:
template<class Visitor> template<class Visitor>
int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v );
template<class Visitor> template<class Visitor>
int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); int Query( const SHAPE* aShape, int aMinDistance, Visitor& v );
@ -64,15 +64,14 @@ public:
ItemSet::iterator begin() { return m_allItems.begin(); } ItemSet::iterator begin() { return m_allItems.begin(); }
ItemSet::iterator end() { return m_allItems.end(); } ItemSet::iterator end() { return m_allItems.end(); }
bool Contains ( PNS_ITEM *aItem ) const { bool Contains( PNS_ITEM* aItem ) const
{
return m_allItems.find( aItem ) != m_allItems.end(); return m_allItems.find( aItem ) != m_allItems.end();
} }
int Size() const { return m_allItems.size(); } int Size() const { return m_allItems.size(); }
private: private:
static const int MaxSubIndices = 64; static const int MaxSubIndices = 64;
static const int SI_Multilayer = 2; static const int SI_Multilayer = 2;
static const int SI_SegDiagonal = 0; static const int SI_SegDiagonal = 0;
@ -91,11 +90,13 @@ private:
ItemSet m_allItems; ItemSet m_allItems;
}; };
PNS_INDEX::PNS_INDEX() PNS_INDEX::PNS_INDEX()
{ {
memset( m_subIndices, 0, sizeof( m_subIndices ) ); memset( m_subIndices, 0, sizeof( m_subIndices ) );
} }
PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
{ {
int idx_n = -1; int idx_n = -1;
@ -107,6 +108,7 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
idx_n = SI_Multilayer; idx_n = SI_Multilayer;
break; break;
case PNS_ITEM::SOLID: case PNS_ITEM::SOLID:
{ {
if( l.IsMultilayer() ) if( l.IsMultilayer() )
@ -115,15 +117,19 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
idx_n = SI_PadsTop; idx_n = SI_PadsTop;
else if( l.Start() == 15 ) else if( l.Start() == 15 )
idx_n = SI_PadsBottom; idx_n = SI_PadsBottom;
break; break;
} }
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
case PNS_ITEM::LINE: case PNS_ITEM::LINE:
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
break; break;
default: default:
break; break;
} }
assert( idx_n >= 0 && idx_n < MaxSubIndices ); assert( idx_n >= 0 && idx_n < MaxSubIndices );
if( !m_subIndices[idx_n] ) if( !m_subIndices[idx_n] )
@ -132,23 +138,26 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
return m_subIndices[idx_n]; return m_subIndices[idx_n];
} }
void PNS_INDEX::Add( PNS_ITEM* aItem ) void PNS_INDEX::Add( PNS_ITEM* aItem )
{ {
ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem );
idx->Add( aItem ); idx->Add( aItem );
m_allItems.insert( aItem ); m_allItems.insert( aItem );
int net = aItem->GetNet(); int net = aItem->GetNet();
if( net >= 0 ) if( net >= 0 )
{ {
m_netMap[net].push_back( aItem ); m_netMap[net].push_back( aItem );
} }
} }
void PNS_INDEX::Remove( PNS_ITEM* aItem ) void PNS_INDEX::Remove( PNS_ITEM* aItem )
{ {
ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem );
idx->Remove( aItem ); idx->Remove( aItem );
m_allItems.erase( aItem ); m_allItems.erase( aItem );
@ -158,27 +167,30 @@ void PNS_INDEX::Remove( PNS_ITEM *aItem )
m_netMap[net].remove( aItem ); m_netMap[net].remove( aItem );
} }
void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
{ {
Remove( aOldItem ); Remove( aOldItem );
Add( aNewItem ); Add( aNewItem );
} }
template<class Visitor> template<class Visitor>
int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v )
{ {
if( !m_subIndices[index] ) if( !m_subIndices[index] )
return 0; return 0;
return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); return m_subIndices[index]->Query( aShape, aMinDistance, v, false );
} }
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v )
{ {
const SHAPE* shape = aItem->GetShape(); const SHAPE* shape = aItem->GetShape();
int total = 0; int total = 0;
total += querySingle( SI_Multilayer, shape, aMinDistance, v ); total += querySingle( SI_Multilayer, shape, aMinDistance, v );
const PNS_LAYERSET layers = aItem->GetLayers(); const PNS_LAYERSET layers = aItem->GetLayers();
@ -188,29 +200,33 @@ template<class Visitor>
total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v );
total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
for( int i = layers.Start(); i <= layers.End(); ++i ) for( int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v );
}
} else { else
{
int l = layers.Start(); int l = layers.Start();
if( l == 0 ) if( l == 0 )
total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v );
else if( l == 15 ) else if( l == 15 )
total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v );
} }
return total; return total;
} }
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v )
{ {
int total = 0; int total = 0;
for( int i = 0; i < MaxSubIndices; i++ ) for( int i = 0; i < MaxSubIndices; i++ )
total += querySingle( i, aShape, aMinDistance, v ); total += querySingle( i, aShape, aMinDistance, v );
return total; return total;
} }
@ -220,22 +236,28 @@ void PNS_INDEX::Clear()
for( int i = 0; i < MaxSubIndices; ++i ) for( int i = 0; i < MaxSubIndices; ++i )
{ {
ItemShapeIndex* idx = m_subIndices[i]; ItemShapeIndex* idx = m_subIndices[i];
if( idx ) if( idx )
delete idx; delete idx;
m_subIndices[i] = NULL; m_subIndices[i] = NULL;
} }
} }
PNS_INDEX::~PNS_INDEX() PNS_INDEX::~PNS_INDEX()
{ {
Clear(); Clear();
} }
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet )
{ {
if( m_netMap.find( aNet ) == m_netMap.end() ) if( m_netMap.find( aNet ) == m_netMap.end() )
return NULL; return NULL;
return &m_netMap[aNet]; return &m_netMap[aNet];
} }
#endif #endif

View File

@ -21,7 +21,8 @@
#include "pns_item.h" #include "pns_item.h"
#include "pns_line.h" #include "pns_line.h"
bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{ {
// same nets? no collision! // same nets? no collision!
if( m_net == aOther->m_net ) if( m_net == aOther->m_net )
@ -36,7 +37,9 @@ bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNee
// fixme: MTV // fixme: MTV
} }
bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{ {
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
return true; return true;
@ -45,28 +48,42 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V
if( aOther->m_kind == LINE ) if( aOther->m_kind == LINE )
{ {
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
if( line->EndsWithVia() ) if( line->EndsWithVia() )
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV,
aMTV );
} }
return false; return false;
} }
const std::string PNS_ITEM::GetKindStr() const const std::string PNS_ITEM::GetKindStr() const
{ {
switch( m_kind ) switch( m_kind )
{ {
case LINE: return "line"; case LINE:
case SEGMENT: return "segment"; return "line";
case VIA: return "via";
case JOINT: return "joint"; case SEGMENT:
case SOLID: return "solid"; return "segment";
default: return "unknown";
case VIA:
return "via";
case JOINT:
return "joint";
case SOLID:
return "solid";
default:
return "unknown";
} }
} }
PNS_ITEM::~PNS_ITEM() PNS_ITEM::~PNS_ITEM()
{ {
} }

View File

@ -41,11 +41,11 @@ class PNS_NODE;
class PNS_ITEM class PNS_ITEM
{ {
public: public:
static const int UnusedNet = INT_MAX; static const int UnusedNet = INT_MAX;
///> Supported item types ///> Supported item types
enum PnsKind { enum PnsKind
{
SOLID = 1, SOLID = 1,
LINE = 2, LINE = 2,
JOINT = 4, JOINT = 4,
@ -88,8 +88,6 @@ public:
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
}; };
PnsKind GetKind() const { return m_kind; } PnsKind GetKind() const { return m_kind; }
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; }
@ -106,7 +104,10 @@ public:
///> Layers accessors ///> Layers accessors
const PNS_LAYERSET& GetLayers() const { return m_layers; } const PNS_LAYERSET& GetLayers() const { return m_layers; }
void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; }
void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); } void SetLayer( int aLayer )
{
m_layers = PNS_LAYERSET( aLayer, aLayer );
}
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned.
void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; }
@ -117,29 +118,31 @@ public:
void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; }
PNS_NODE* GetWorld() const { return m_world; } PNS_NODE* GetWorld() const { return m_world; }
///> Collision function. Checks if the item aOther is closer to us than ///> Collision function. Checks if the item aOther is closer to us than
/// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the /// aClearance and returns true if so. It can also calculate a minimum translation vector that
/// collision if needed. /// resolves the collision if needed.
virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
///> A shortcut without MTV calculation ///> A shortcut without MTV calculation
bool Collide( const PNS_ITEM* aOther, int aClearance ) const bool Collide( const PNS_ITEM* aOther, int aClearance ) const
{ {
VECTOR2I dummy; VECTOR2I dummy;
return Collide( aOther, aClearance, false, dummy ); return Collide( aOther, aClearance, false, dummy );
} }
///> Returns the geometric shape of the item ///> Returns the geometric shape of the item
virtual const SHAPE* GetShape() const { virtual const SHAPE* GetShape() const
{
return NULL; return NULL;
} }
private: private:
bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
protected: protected:
PnsKind m_kind; PnsKind m_kind;
BOARD_ITEM* m_parent; BOARD_ITEM* m_parent;
@ -151,5 +154,5 @@ protected:
int m_net; int m_net;
}; };
#endif // __PNS_ITEM_H #endif // __PNS_ITEM_Ha

View File

@ -25,48 +25,57 @@
PNS_ITEMSET::PNS_ITEMSET() PNS_ITEMSET::PNS_ITEMSET()
{ {
} }
PNS_ITEMSET::~PNS_ITEMSET() PNS_ITEMSET::~PNS_ITEMSET()
{ {
} }
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd ) PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
{ {
ItemVector newItems; ItemVector newItems;
PNS_LAYERSET l; PNS_LAYERSET l;
if( aEnd < 0 ) if( aEnd < 0 )
l = PNS_LAYERSET( aStart ); l = PNS_LAYERSET( aStart );
else else
l = PNS_LAYERSET( aStart, aEnd ); l = PNS_LAYERSET( aStart, aEnd );
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetLayers().Overlaps( l ) ) if( item->GetLayers().Overlaps( l ) )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
return *this; return *this;
} }
PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask ) PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
{ {
ItemVector newItems; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetKind() & aKindMask ) if( item->GetKind() & aKindMask )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
return *this; return *this;
} }
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet ) PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
{ {
ItemVector newItems; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM * item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetNet() == aNet ) if( item->GetNet() == aNet )
newItems.push_back( item ); newItems.push_back( item );
m_items = newItems; m_items = newItems;
return *this; return *this;
} }

View File

@ -28,13 +28,13 @@
/** /**
* Class PNS_ITEMSET * Class PNS_ITEMSET
* *
* Holds a list of board items, that can be filtered against net, kinds, layers, etc. * Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/ **/
class PNS_ITEMSET class PNS_ITEMSET
{ {
public: public:
typedef std::vector<PNS_ITEM*> ItemVector; typedef std::vector<PNS_ITEM*> ItemVector;
PNS_ITEMSET(); PNS_ITEMSET();
@ -60,3 +60,4 @@ private:
}; };
#endif #endif

View File

@ -32,18 +32,20 @@
/** /**
* Class PNS_JOINT * Class PNS_JOINT
* *
* Represents a 2D point on a given set of layers and belonging to a certain net, * Represents a 2D point on a given set of layers and belonging to a certain
* that links together a number of board items. * net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items. * A hash table of joints is used by the router to follow connectivity between
* the items.
**/ **/
class PNS_JOINT : public PNS_ITEM class PNS_JOINT : public PNS_ITEM
{ {
public: public:
typedef std::vector<PNS_ITEM*> LinkedItems; typedef std::vector<PNS_ITEM*> LinkedItems;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed ///> Joints are hashed by their position, layers and net.
struct HashTag { /// Linked items are, obviously, not hashed
struct HashTag
{
VECTOR2I pos; VECTOR2I pos;
int net; int net;
}; };
@ -51,7 +53,8 @@ public:
PNS_JOINT() : PNS_JOINT() :
PNS_ITEM( JOINT ) {} PNS_ITEM( JOINT ) {}
PNS_JOINT(const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1): PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet = -1 ) :
PNS_ITEM( JOINT ) PNS_ITEM( JOINT )
{ {
m_tag.pos = aPos; m_tag.pos = aPos;
@ -75,28 +78,33 @@ public:
return NULL; return NULL;
} }
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer. ///> Returns true if the joint is a trivial line corner, connecting two
/// segments of the same net, on the same layer.
bool IsLineCorner() const bool IsLineCorner() const
{ {
if( m_linkedItems.size() != 2 ) if( m_linkedItems.size() != 2 )
return false; return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || m_linkedItems[1]->GetKind() != SEGMENT ) if( m_linkedItems[0]->GetKind() != SEGMENT ||
m_linkedItems[1]->GetKind() != SEGMENT )
return false; return false;
PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]); PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]);
PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]); PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]);
// joints between segments of different widths are not trivial. // joints between segments of different widths are not trivial.
return (seg1->GetWidth() == seg2->GetWidth()); return seg1->GetWidth() == seg2->GetWidth();
} }
///> Links the joint to a given board item (when it's added to the PNS_NODE) ///> Links the joint to a given board item (when it's added to the PNS_NODE)
void Link( PNS_ITEM* aItem ) void Link( PNS_ITEM* aItem )
{ {
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem); LinkedItems::iterator f = std::find( m_linkedItems.begin(),
m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() ) if( f != m_linkedItems.end() )
return; return;
m_linkedItems.push_back( aItem ); m_linkedItems.push_back( aItem );
} }
@ -104,10 +112,13 @@ public:
///> Returns true if the joint became dangling after unlinking. ///> Returns true if the joint became dangling after unlinking.
bool Unlink( PNS_ITEM* aItem ) bool Unlink( PNS_ITEM* aItem )
{ {
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem); LinkedItems::iterator f = std::find( m_linkedItems.begin(),
m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() ) if( f != m_linkedItems.end() )
m_linkedItems.erase( f ); m_linkedItems.erase( f );
return (m_linkedItems.size() == 0);
return m_linkedItems.size() == 0;
} }
///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns ///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
@ -130,9 +141,12 @@ public:
int LinkCount( int aMask = -1 ) const int LinkCount( int aMask = -1 ) const
{ {
int n = 0; int n = 0;
for(LinkedItems::const_iterator i = m_linkedItems.begin(); i!= m_linkedItems.end(); ++i)
for( LinkedItems::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i )
if( (*i)->GetKind() & aMask ) if( (*i)->GetKind() & aMask )
n++; n++;
return n; return n;
} }
@ -151,17 +165,18 @@ public:
m_layers.Merge( aJoint.m_layers ); m_layers.Merge( aJoint.m_layers );
// fixme: duplicate links (?) // fixme: duplicate links (?)
for(LinkedItems::const_iterator i =aJoint.m_linkedItems.begin(); i!=aJoint.m_linkedItems.end();++i) for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin();
i != aJoint.m_linkedItems.end(); ++i )
m_linkedItems.push_back( *i ); m_linkedItems.push_back( *i );
} }
bool Overlaps( const PNS_JOINT& rhs ) const bool Overlaps( const PNS_JOINT& rhs ) const
{ {
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net && m_layers.Overlaps(rhs.m_layers); return m_tag.pos == rhs.m_tag.pos &&
m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
} }
private: private:
///> hash tag for unordered_multimap ///> hash tag for unordered_multimap
HashTag m_tag; HashTag m_tag;
@ -171,18 +186,22 @@ private:
// hash function & comparison operator for boost::unordered_map<> // hash function & comparison operator for boost::unordered_map<>
inline bool operator==(PNS_JOINT::HashTag const& p1, PNS_JOINT::HashTag const& p2) inline bool operator==( PNS_JOINT::HashTag const& p1,
PNS_JOINT::HashTag const& p2 )
{ {
return p1.pos == p2.pos && p1.net == p2.net; return p1.pos == p2.pos && p1.net == p2.net;
} }
inline std::size_t hash_value( PNS_JOINT::HashTag const& p ) inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
{ {
std::size_t seed = 0; std::size_t seed = 0;
boost::hash_combine( seed, p.pos.x ); boost::hash_combine( seed, p.pos.x );
boost::hash_combine( seed, p.pos.y ); boost::hash_combine( seed, p.pos.y );
boost::hash_combine( seed, p.net ); boost::hash_combine( seed, p.net );
return seed; return seed;
} }
#endif // __PNS_JOINT_H #endif // __PNS_JOINT_H

View File

@ -28,11 +28,9 @@
* *
* Represents a contiguous set of PCB layers. * Represents a contiguous set of PCB layers.
*/ */
class PNS_LAYERSET class PNS_LAYERSET
{ {
public: public:
PNS_LAYERSET() : PNS_LAYERSET() :
m_start( -1 ), m_start( -1 ),
m_end( -1 ) m_end( -1 )
@ -42,6 +40,7 @@ class PNS_LAYERSET
{ {
if( aStart > aEnd ) if( aStart > aEnd )
std::swap( aStart, aEnd ); std::swap( aStart, aEnd );
m_start = aStart; m_start = aStart;
m_end = aEnd; m_end = aEnd;
} }
@ -80,11 +79,13 @@ class PNS_LAYERSET
return m_start != m_end; return m_start != m_end;
} }
int Start() const { int Start() const
{
return m_start; return m_start;
} }
int End() const { int End() const
{
return m_end; return m_end;
} }
@ -99,6 +100,7 @@ class PNS_LAYERSET
if( aOther.m_start < m_start ) if( aOther.m_start < m_start )
m_start = aOther.m_start; m_start = aOther.m_start;
if( aOther.m_end > m_end ) if( aOther.m_end > m_end )
m_end = aOther.m_end; m_end = aOther.m_end;
} }
@ -110,9 +112,9 @@ class PNS_LAYERSET
} }
private: private:
int m_start; int m_start;
int m_end; int m_end;
}; };
#endif // __PNS_LAYERSET_H #endif // __PNS_LAYERSET_H

View File

@ -23,7 +23,6 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include "pns_line.h" #include "pns_line.h"
#include "pns_node.h" #include "pns_node.h"
#include "pns_via.h" #include "pns_via.h"
@ -49,6 +48,7 @@ PNS_LINE *PNS_LINE::Clone() const
return l; return l;
} }
PNS_LINE* PNS_LINE::CloneProperties() const PNS_LINE* PNS_LINE::CloneProperties() const
{ {
PNS_LINE* l = new PNS_LINE(); PNS_LINE* l = new PNS_LINE();
@ -61,9 +61,11 @@ PNS_LINE *PNS_LINE::CloneProperties() const
return l; return l;
} }
PNS_SEGMENT* PNS_SEGMENT::Clone() const PNS_SEGMENT* PNS_SEGMENT::Clone() const
{ {
PNS_SEGMENT* s = new PNS_SEGMENT; PNS_SEGMENT* s = new PNS_SEGMENT;
s->m_width = m_width; s->m_width = m_width;
s->m_net = m_net; s->m_net = m_net;
s->m_shape = m_shape; s->m_shape = m_shape;
@ -72,6 +74,7 @@ PNS_SEGMENT *PNS_SEGMENT::Clone() const
return s; // assert(false); return s; // assert(false);
} }
#if 1 #if 1
bool PNS_LINE::MergeObtuseSegments() bool PNS_LINE::MergeObtuseSegments()
{ {
@ -90,6 +93,7 @@ bool PNS_LINE::MergeObtuseSegments( )
iter++; iter++;
int n_segs = current_path.SegmentCount(); int n_segs = current_path.SegmentCount();
int max_step = n_segs - 2; int max_step = n_segs - 2;
if( step > max_step ) if( step > max_step )
step = max_step; step = max_step;
@ -116,7 +120,9 @@ bool PNS_LINE::MergeObtuseSegments( )
{ {
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} else { }
else
{
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} }
@ -140,6 +146,7 @@ bool PNS_LINE::MergeObtuseSegments( )
} }
} }
} }
n++; n++;
} }
@ -150,12 +157,15 @@ bool PNS_LINE::MergeObtuseSegments( )
m_line = current_path; m_line = current_path;
return m_line.SegmentCount() < segs_pre; return m_line.SegmentCount() < segs_pre;
} }
step--; step--;
} }
} }
return m_line.SegmentCount() < segs_pre; return m_line.SegmentCount() < segs_pre;
} }
bool PNS_LINE::MergeSegments() bool PNS_LINE::MergeSegments()
{ {
int step = m_line.PointCount() - 3; int step = m_line.PointCount() - 3;
@ -173,6 +183,7 @@ bool PNS_LINE::MergeSegments( )
iter++; iter++;
int n_segs = current_path.SegmentCount(); int n_segs = current_path.SegmentCount();
int max_step = n_segs - 2; int max_step = n_segs - 2;
if( step > max_step ) if( step > max_step )
step = max_step; step = max_step;
@ -193,11 +204,12 @@ bool PNS_LINE::MergeSegments( )
if( n > 0 ) if( n > 0 )
{ {
SHAPE_LINE_CHAIN path_straight = DIRECTION_45().BuildInitialTrace(s1.a, s2.a, false); SHAPE_LINE_CHAIN path_straight = DIRECTION_45().BuildInitialTrace( s1.a,
SHAPE_LINE_CHAIN path_diagonal = DIRECTION_45().BuildInitialTrace(s1.a, s2.a, true); s2.a,
false );
SHAPE_LINE_CHAIN path_diagonal = DIRECTION_45().BuildInitialTrace( s1.a,
s2.a,
true );
} }
if( DIRECTION_45( s1 ) == DIRECTION_45( s2 ) ) if( DIRECTION_45( s1 ) == DIRECTION_45( s2 ) )
@ -219,10 +231,7 @@ bool PNS_LINE::MergeSegments( )
found_anything = true; found_anything = true;
break; break;
} }
} }
} }
else if( DIRECTION_45( s1 ).IsObtuse( DIRECTION_45( s2 ) ) ) else if( DIRECTION_45( s1 ).IsObtuse( DIRECTION_45( s2 ) ) )
{ {
@ -232,7 +241,9 @@ bool PNS_LINE::MergeSegments( )
{ {
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} else { }
else
{
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} }
@ -255,8 +266,8 @@ bool PNS_LINE::MergeSegments( )
break; break;
} }
} }
} }
n++; n++;
} }
@ -267,18 +278,20 @@ bool PNS_LINE::MergeSegments( )
m_line = current_path; m_line = current_path;
return m_line.SegmentCount() < segs_pre; return m_line.SegmentCount() < segs_pre;
} }
step--; step--;
} }
} }
return m_line.SegmentCount() < segs_pre; return m_line.SegmentCount() < segs_pre;
} }
#endif #endif
int PNS_LINE::CountCorners( int aAngles ) int PNS_LINE::CountCorners( int aAngles )
{ {
int count = 0; int count = 0;
for( int i = 0; i < m_line.SegmentCount() - 1; i++ ) for( int i = 0; i < m_line.SegmentCount() - 1; i++ )
{ {
const SEG seg1 = m_line.CSegment( i ); const SEG seg1 = m_line.CSegment( i );
@ -288,12 +301,15 @@ int PNS_LINE::CountCorners(int aAngles)
const DIRECTION_45 dir2( seg2 ); const DIRECTION_45 dir2( seg2 );
DIRECTION_45::AngleType a = dir1.Angle( dir2 ); DIRECTION_45::AngleType a = dir1.Angle( dir2 );
if( a & aAngles ) if( a & aAngles )
count++; count++;
} }
return count; return count;
} }
// #define DUMP_TEST_CASES // #define DUMP_TEST_CASES
// fixme: damn f*****g inefficient and incredibly crappily written // fixme: damn f*****g inefficient and incredibly crappily written
@ -303,7 +319,6 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPostPath, SHAPE_LINE_CHAIN& aPostPath,
bool aCw ) const bool aCw ) const
{ {
typedef SHAPE_LINE_CHAIN::Intersection Intersection; typedef SHAPE_LINE_CHAIN::Intersection Intersection;
SHAPE_LINE_CHAIN l_orig( m_line ); SHAPE_LINE_CHAIN l_orig( m_line );
@ -323,14 +338,14 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
#endif #endif
aObstacle.Intersect( m_line, isects ); aObstacle.Intersect( m_line, isects );
// printf("NewWalk intersectiosn :%d\n" ,isects.size()); // printf("NewWalk intersectiosn :%d\n" ,isects.size());
if( !aCw ) if( !aCw )
l_hull = aObstacle.Reverse(); l_hull = aObstacle.Reverse();
else else
l_hull = aObstacle; l_hull = aObstacle;
BOOST_FOREACH( Intersection isect, isects ) BOOST_FOREACH( Intersection isect, isects ) {
{
l_orig.Split( isect.p ); l_orig.Split( isect.p );
l_hull.Split( isect.p ); l_hull.Split( isect.p );
} }
@ -361,7 +376,6 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
inside.push_back( in ); inside.push_back( in );
} }
for( int i = l_orig.PointCount() - 1; i >= 1; i-- ) for( int i = l_orig.PointCount() - 1; i >= 1; i-- )
if( inside[i] && outside[i - 1] ) if( inside[i] && outside[i - 1] )
{ {
@ -375,7 +389,8 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
{ {
l_orig.Remove( i, -1 ); l_orig.Remove( i, -1 );
// n = i; // n = i;
} else if(!inside[i]) }
else if( !inside[i] )
break; break;
if( !outside.size() && on_edge.size() < 2 ) if( !outside.size() && on_edge.size() < 2 )
@ -389,16 +404,19 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
{ {
if( last_pre < 0 ) if( last_pre < 0 )
aPrePath.Append( p ); aPrePath.Append( p );
path.Append( p ); path.Append( p );
} }
else if( on_edge[i] ) else if( on_edge[i] )
{ {
int li = -1; int li = -1;
if( last_pre < 0 ) if( last_pre < 0 )
{ {
aPrePath.Append( p ); aPrePath.Append( p );
last_pre = path.PointCount(); last_pre = path.PointCount();
} }
if( i == l_orig.PointCount() - 1 || outside[i + 1] ) if( i == l_orig.PointCount() - 1 || outside[i + 1] )
{ {
path.Append( p ); path.Append( p );
@ -408,22 +426,27 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
int vi2 = l_hull.Find( l_orig.CPoint( i ) ); int vi2 = l_hull.Find( l_orig.CPoint( i ) );
path.Append( l_hull.CPoint( vi2 ) ); path.Append( l_hull.CPoint( vi2 ) );
for(int j = (vi2 + 1) % l_hull.PointCount(); j != vi2; j = (j + 1) % l_hull.PointCount())
for( int j = (vi2 + 1) % l_hull.PointCount();
j != vi2;
j = (j + 1) % l_hull.PointCount() )
{ {
path.Append( l_hull.CPoint( j ) ); path.Append( l_hull.CPoint( j ) );
li = l_orig.Find( l_hull.CPoint( j ) ); li = l_orig.Find( l_hull.CPoint( j ) );
if(li >= 0 && (li == (l_orig.PointCount() - 1) || outside[li+1]))
if( li >= 0 && ( li == (l_orig.PointCount() - 1 ) ||
outside[li + 1]) )
break; break;
} }
if(li >= 0) { if( li >= 0 )
{
if( i >= li ) if( i >= li )
break; break;
else { else
i = li; i = li;
} }
} }
}
first_post = path.PointCount() - 1; first_post = path.PointCount() - 1;
} }
@ -433,12 +456,14 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
return; return;
aWalkaroundPath = path.Slice( last_pre, first_post ); aWalkaroundPath = path.Slice( last_pre, first_post );
if( first_post >= 0 ) if( first_post >= 0 )
aPostPath = path.Slice( first_post, -1 ); aPostPath = path.Slice( first_post, -1 );
} }
bool PNS_LINE::onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const
bool PNS_LINE::onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei,
bool& is_vertex ) const
{ {
int vtx = obstacle.Find( p ); int vtx = obstacle.Find( p );
@ -462,15 +487,23 @@ bool PNS_LINE::onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, boo
return false; return false;
} }
bool PNS_LINE::walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const
bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line,
const SHAPE_LINE_CHAIN& obstacle,
bool reverse,
VECTOR2I& ip,
int& index_o,
int& index_l,
bool& is_vertex ) const
{ {
int sc = line.SegmentCount(); int sc = line.SegmentCount();
for( int i = 0; i < line.SegmentCount(); i++ ) for( int i = 0; i < line.SegmentCount(); i++ )
{ {
printf( "check-seg rev %d %d/%d %d\n", reverse, i, sc, sc - 1 - i ); printf( "check-seg rev %d %d/%d %d\n", reverse, i, sc, sc - 1 - i );
SEG tmp = line.CSegment( reverse ? sc - 1 - i : i ); SEG tmp = line.CSegment( reverse ? sc - 1 - i : i );
SEG s( tmp.a, tmp.b ); SEG s( tmp.a, tmp.b );
if( reverse ) if( reverse )
{ {
s.a = tmp.b; s.a = tmp.b;
@ -481,7 +514,8 @@ bool PNS_LINE::walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &ob
{ {
index_l = (reverse ? sc - 1 - i : i); index_l = (reverse ? sc - 1 - i : i);
ip = s.a; ip = s.a;
printf("vertex %d on-%s %d\n", index_l, is_vertex?"vertex":"edge",index_o); printf( "vertex %d on-%s %d\n", index_l,
is_vertex ? "vertex" : "edge", index_o );
return true; return true;
} }
@ -489,7 +523,8 @@ bool PNS_LINE::walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &ob
{ {
index_l = (reverse ? sc - 1 - i - 1 : i + 1); index_l = (reverse ? sc - 1 - i - 1 : i + 1);
ip = s.b; ip = s.b;
printf("vertex %d on-%s %d\n", index_l, is_vertex?"vertex":"edge",index_o); printf( "vertex %d on-%s %d\n", index_l,
is_vertex ? "vertex" : "edge", index_o );
return true; return true;
} }
@ -505,10 +540,16 @@ bool PNS_LINE::walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &ob
return true; return true;
} }
} }
return false; return false;
} }
bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const
bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN obstacle,
SHAPE_LINE_CHAIN& pre,
SHAPE_LINE_CHAIN& walk,
SHAPE_LINE_CHAIN& post,
bool cw ) const
{ {
const SHAPE_LINE_CHAIN& line = GetCLine(); const SHAPE_LINE_CHAIN& line = GetCLine();
VECTOR2I ip_start; VECTOR2I ip_start;
@ -521,11 +562,18 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
if( line.SegmentCount() < 1 ) if( line.SegmentCount() < 1 )
return false; return false;
if(obstacle.PointInside(line.CPoint(0)) || obstacle.PointInside(line.CPoint(-1))) if( obstacle.PointInside( line.CPoint( 0 ) ) ||
obstacle.PointInside( line.CPoint( -1 ) ) )
return false; return false;
// printf("forward:\n"); // printf("forward:\n");
bool found = walkScan(line, obstacle, false, ip_start, index_o_start, index_l_start, is_vertex_start); bool found = walkScan( line,
obstacle,
false,
ip_start,
index_o_start,
index_l_start,
is_vertex_start );
// printf("reverse:\n"); // printf("reverse:\n");
found |= walkScan( line, obstacle, true, ip_end, index_o_end, index_l_end, is_vertex_end ); found |= walkScan( line, obstacle, true, ip_end, index_o_end, index_l_end, is_vertex_end );
@ -535,7 +583,6 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
return true; return true;
} }
pre = line.Slice( 0, index_l_start ); pre = line.Slice( 0, index_l_start );
pre.Append( ip_start ); pre.Append( ip_start );
walk.Clear(); walk.Clear();
@ -555,10 +602,13 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
break; break;
is++; is++;
if( is == obstacle.PointCount() ) if( is == obstacle.PointCount() )
is = 0; is = 0;
} }
} else { }
else
{
int is = index_o_start; int is = index_o_start;
int ie = ( is_vertex_end ? index_o_end : index_o_end ) % obstacle.PointCount(); int ie = ( is_vertex_end ? index_o_end : index_o_end ) % obstacle.PointCount();
@ -566,15 +616,15 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
{ {
printf( "is %d\n", is ); printf( "is %d\n", is );
walk.Append( obstacle.CPoint( is ) ); walk.Append( obstacle.CPoint( is ) );
if( is == ie ) if( is == ie )
break; break;
is--; is--;
if( is < 0 ) if( is < 0 )
is = obstacle.PointCount() - 1; is = obstacle.PointCount() - 1;
} }
} }
walk.Append( ip_end ); walk.Append( ip_end );
@ -591,27 +641,28 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
// } // }
return true; return true;
} }
void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath, SHAPE_LINE_CHAIN& aPath,
bool aCw ) const bool aCw ) const
{ {
SHAPE_LINE_CHAIN walk, post; SHAPE_LINE_CHAIN walk, post;
NewWalkaround( aObstacle, aPath, walk, post, aCw ); NewWalkaround( aObstacle, aPath, walk, post, aCw );
aPath.Append( walk ); aPath.Append( walk );
aPath.Append( post ); aPath.Append( post );
aPath.Simplify(); aPath.Simplify();
} }
void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle, void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath, SHAPE_LINE_CHAIN& aPath,
bool aCw ) const bool aCw ) const
{ {
SHAPE_LINE_CHAIN walk, post; SHAPE_LINE_CHAIN walk, post;
Walkaround( aObstacle, aPath, walk, post, aCw ); Walkaround( aObstacle, aPath, walk, post, aCw );
aPath.Append( walk ); aPath.Append( walk );
aPath.Append( post ); aPath.Append( post );
@ -631,13 +682,12 @@ const SHAPE_LINE_CHAIN PNS_SEGMENT::Hull(int aClearance, int aWalkaroundThicknes
VECTOR2I p0 = dir.Perpendicular().Resize( d ); VECTOR2I p0 = dir.Perpendicular().Resize( d );
VECTOR2I ds = dir.Perpendicular().Resize( x / 2 ); VECTOR2I ds = dir.Perpendicular().Resize( x / 2 );
VECTOR2I pd = dir.Resize( x / 2 ); VECTOR2I pd = dir.Resize( x / 2 );
VECTOR2I dp = dir.Resize( d ); VECTOR2I dp = dir.Resize( d );
SHAPE_LINE_CHAIN s; SHAPE_LINE_CHAIN s;
s.SetClosed( true ); s.SetClosed( true );
s.Append( b + p0 + pd ); s.Append( b + p0 + pd );
@ -654,7 +704,6 @@ const SHAPE_LINE_CHAIN PNS_SEGMENT::Hull(int aClearance, int aWalkaroundThicknes
return s.Reverse(); return s.Reverse();
else else
return s; return s;
} }
@ -664,18 +713,23 @@ bool PNS_LINE::Is45Degree()
{ {
const SEG& s = m_line.CSegment( i ); const SEG& s = m_line.CSegment( i );
double angle = 180.0 / M_PI * atan2((double)s.b.y - (double)s.a.y, (double)s.b.x - (double)s.a.x); double angle = 180.0 / M_PI *
atan2( (double) s.b.y - (double) s.a.y,
(double) s.b.x - (double) s.a.x );
if( angle < 0 ) if( angle < 0 )
angle += 360.0; angle += 360.0;
double angle_a = fabs( fmod( angle, 45.0 ) ); double angle_a = fabs( fmod( angle, 45.0 ) );
if( angle_a > 1.0 && angle_a < 44.0 ) if( angle_a > 1.0 && angle_a < 44.0 )
return false; return false;
} }
return true; return true;
} }
const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const
{ {
PNS_LINE l( *this ); PNS_LINE l( *this );
@ -692,6 +746,7 @@ const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE *aNode ) const
return l; return l;
} }
void PNS_LINE::ShowLinks() void PNS_LINE::ShowLinks()
{ {
if( !m_segmentRefs ) if( !m_segmentRefs )
@ -699,6 +754,10 @@ void PNS_LINE::ShowLinks()
printf( "line %p: no links\n", this ); printf( "line %p: no links\n", this );
return; return;
} }
printf( "line %p: %d linked segs\n", this, m_segmentRefs->size() ); printf( "line %p: %d linked segs\n", this, m_segmentRefs->size() );
for (int i= 0; i<(int)m_segmentRefs->size(); i++) printf("seg %d: %p\n", i, (*m_segmentRefs)[i]) ;
for( int i = 0; i < (int) m_segmentRefs->size(); i++ )
printf( "seg %d: %p\n", i, (*m_segmentRefs)[i] );
} }

View File

@ -38,15 +38,18 @@ class PNS_VIA;
/** /**
* Class PNS_LINE * Class PNS_LINE
* *
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads, * Represents a track on a PCB, connecting two non-trivial joints (that is,
* junctions between multiple traces or two traces different widths and combinations of these). * vias, pads, junctions between multiple traces or two traces different widths
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on * and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* a via/pad/segment that belongs/begins them. * Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
* *
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments * PNS_LINEs can be either loose (consisting of segments that do not belong to
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends. * any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends.
* *
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff. * A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/ */
class PNS_LINE : public PNS_ITEM class PNS_LINE : public PNS_ITEM
@ -71,7 +74,6 @@ public:
m_hasVia = false; m_hasVia = false;
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
SetLayer( aLayer ); SetLayer( aLayer );
} }
PNS_LINE( const PNS_LINE& aOther ) : PNS_LINE( const PNS_LINE& aOther ) :
@ -114,7 +116,8 @@ public:
virtual PNS_LINE* Clone() const; virtual PNS_LINE* Clone() const;
///> clones the line without cloning the shape (just the properties - net, width, layers, etc.) ///> clones the line without cloning the shape
///> (just the properties - net, width, layers, etc.)
PNS_LINE* CloneProperties() const; PNS_LINE* CloneProperties() const;
int GetLayer() const { return GetLayers().Start(); } int GetLayer() const { return GetLayers().Start(); }
@ -134,11 +137,12 @@ public:
{ {
if( !m_segmentRefs ) if( !m_segmentRefs )
m_segmentRefs = new std::vector<PNS_SEGMENT*> (); m_segmentRefs = new std::vector<PNS_SEGMENT*> ();
m_segmentRefs->push_back( aSeg ); m_segmentRefs->push_back( aSeg );
} }
///> Returns a list of segments from the owning node that constitute this line (or NULL if ///> Returns a list of segments from the owning node that constitute this
///> the line is loose) ///> line (or NULL if the line is loose)
LinkedSegments* GetLinkedSegments() LinkedSegments* GetLinkedSegments()
{ {
return m_segmentRefs; return m_segmentRefs;
@ -149,10 +153,12 @@ public:
if( !m_segmentRefs ) if( !m_segmentRefs )
return false; return false;
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end(); return std::find( m_segmentRefs->begin(), m_segmentRefs->end(),
aSeg ) != m_segmentRefs->end();
} }
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision. ///> Returns this line, but clipped to the nearest obstacle
///> along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const; const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const;
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER) ///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
@ -162,8 +168,8 @@ public:
///> Returns the number of corners of angles specified by mask aAngles. ///> Returns the number of corners of angles specified by mask aAngles.
int CountCorners( int aAngles ); int CountCorners( int aAngles );
///> Calculates a line thightly wrapping a convex hull
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle). ///> of an obstacle object (aObstacle).
///> aPrePath = path from origin to the obstacle ///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle ///> aWalkaroundPath = path around the obstacle
///> aPostPath = past from obstacle till the end ///> aPostPath = past from obstacle till the end
@ -179,13 +185,16 @@ public:
bool aCw ) const; bool aCw ) const;
bool Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const; bool Walkaround( SHAPE_LINE_CHAIN obstacle,
SHAPE_LINE_CHAIN& pre,
SHAPE_LINE_CHAIN& walk,
SHAPE_LINE_CHAIN& post,
bool cw ) const;
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle, void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath, SHAPE_LINE_CHAIN& aPath,
bool aCw ) const; bool aCw ) const;
bool Is45Degree(); bool Is45Degree();
///> Prints out all linked segments ///> Prints out all linked segments
@ -193,7 +202,8 @@ public:
bool EndsWithVia() const { return m_hasVia; } bool EndsWithVia() const { return m_hasVia; }
void AppendVia ( const PNS_VIA &aVia ) { void AppendVia( const PNS_VIA& aVia )
{
m_hasVia = true; m_hasVia = true;
m_via = aVia; m_via = aVia;
m_via.SetNet( m_net ); m_via.SetNet( m_net );
@ -220,7 +230,9 @@ public:
aStart = m_affectedRangeStart; aStart = m_affectedRangeStart;
aEnd = m_affectedRangeEnd; aEnd = m_affectedRangeEnd;
return true; return true;
} else { }
else
{
aStart = 0; aStart = 0;
aEnd = m_line.PointCount(); aEnd = m_line.PointCount();
return false; return false;
@ -229,7 +241,8 @@ public:
private: private:
bool onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, bool& is_vertex ) const; bool onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, bool& is_vertex ) const;
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const; bool walkScan( const SHAPE_LINE_CHAIN& line, const SHAPE_LINE_CHAIN& obstacle,
bool reverse, VECTOR2I& ip, int& index_o, int& index_l, bool& is_vertex ) const;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line. ///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments* m_segmentRefs; LinkedSegments* m_segmentRefs;
@ -238,6 +251,7 @@ private:
SHAPE_LINE_CHAIN m_line; SHAPE_LINE_CHAIN m_line;
int m_width; int m_width;
///> Via at the end and a flag indicating if it's enabled. ///> Via at the end and a flag indicating if it's enabled.
PNS_VIA m_via; PNS_VIA m_via;
bool m_hasVia; bool m_hasVia;
@ -246,6 +260,5 @@ private:
int m_affectedRangeEnd; int m_affectedRangeEnd;
}; };
#endif // __PNS_LINE_H #endif // __PNS_LINE_H

View File

@ -46,12 +46,14 @@ PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_NODE *aWorld )
m_shove = NULL; m_shove = NULL;
}; };
PNS_LINE_PLACER::~PNS_LINE_PLACER() PNS_LINE_PLACER::~PNS_LINE_PLACER()
{ {
if( m_shove ) if( m_shove )
delete m_shove; delete m_shove;
} }
void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings ) void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings )
{ {
m_follow_mouse = aSettings.m_followMouse; m_follow_mouse = aSettings.m_followMouse;
@ -60,10 +62,13 @@ void PNS_LINE_PLACER::ApplySettings ( const PNS_ROUTING_SETTINGS& aSettings )
m_smartPads = aSettings.m_smartPads; m_smartPads = aSettings.m_smartPads;
} }
void PNS_LINE_PLACER::StartPlacement(const VECTOR2I& aStart, int aNet, int aWidth, int aLayer )
void PNS_LINE_PLACER::StartPlacement( const VECTOR2I& aStart, int aNet,
int aWidth, int aLayer )
{ {
m_direction = m_initial_direction; m_direction = m_initial_direction;
TRACE(1, "world %p, intitial-direction %s layer %d\n", m_world % m_direction.Format().c_str() % aLayer); TRACE( 1, "world %p, intitial-direction %s layer %d\n",
m_world % m_direction.Format().c_str() % aLayer );
m_head.SetNet( aNet ); m_head.SetNet( aNet );
m_tail.SetNet( aNet ); m_tail.SetNet( aNet );
m_head.SetWidth( aWidth ); m_head.SetWidth( aWidth );
@ -83,6 +88,7 @@ void PNS_LINE_PLACER::StartPlacement(const VECTOR2I& aStart, int aNet, int aWidt
m_placingVia = false; m_placingVia = false;
} }
void PNS_LINE_PLACER::SetInitialDirection( const DIRECTION_45& aDirection ) void PNS_LINE_PLACER::SetInitialDirection( const DIRECTION_45& aDirection )
{ {
m_initial_direction = aDirection; m_initial_direction = aDirection;
@ -91,13 +97,7 @@ void PNS_LINE_PLACER::SetInitialDirection(const DIRECTION_45& aDirection)
m_direction = aDirection; m_direction = aDirection;
} }
/**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the tail up to the
* intersecting segment and fixes the head direction to match the last segment before the cut.
* @return true if the line has been changed.
*/
bool PNS_LINE_PLACER::handleSelfIntersections() bool PNS_LINE_PLACER::handleSelfIntersections()
{ {
SHAPE_LINE_CHAIN::Intersections ips; SHAPE_LINE_CHAIN::Intersections ips;
@ -141,7 +141,9 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
tail.Clear(); tail.Clear();
head.Clear(); head.Clear();
return true; return true;
} else { }
else
{
// Clip till the last tail segment before intersection. // Clip till the last tail segment before intersection.
// Set the direction to the one of this segment. // Set the direction to the one of this segment.
const SEG last = tail.CSegment( n - 1 ); const SEG last = tail.CSegment( n - 1 );
@ -150,16 +152,11 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
tail.Remove( n, -1 ); tail.Remove( n, -1 );
return true; return true;
} }
return false; return false;
} }
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards wrs
* to the current tail direction.
* @return true if the line has been changed.
*/
bool PNS_LINE_PLACER::handlePullback() bool PNS_LINE_PLACER::handlePullback()
{ {
SHAPE_LINE_CHAIN& head = m_head.GetLine(); SHAPE_LINE_CHAIN& head = m_head.GetLine();
@ -180,26 +177,28 @@ bool PNS_LINE_PLACER::handlePullback()
DIRECTION_45 last_tail( tail.Segment( -1 ) ); DIRECTION_45 last_tail( tail.Segment( -1 ) );
DIRECTION_45::AngleType angle = first_head.Angle( last_tail ); DIRECTION_45::AngleType angle = first_head.Angle( last_tail );
// case 1: we have a defined routing direction, and the currently computed head // case 1: we have a defined routing direction, and the currently computed
// goes in different one. // head goes in different one.
bool pullback_1 = false; // (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head); bool pullback_1 = false; // (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
// case 2: regardless of the current routing direction, if the tail/head extremities form // case 2: regardless of the current routing direction, if the tail/head
// an acute or right angle, reduce the tail by one segment (and hope that further iterations) // extremities form an acute or right angle, reduce the tail by one segment
// will result with a cleaner trace // (and hope that further iterations) will result with a cleaner trace
bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE); bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT ||
angle == DIRECTION_45::ANG_ACUTE);
if( pullback_1 || pullback_2 ) if( pullback_1 || pullback_2 )
{ {
const SEG last = tail.CSegment( -1 ); const SEG last = tail.CSegment( -1 );
m_direction = DIRECTION_45( last ); m_direction = DIRECTION_45( last );
m_p_start = last.a; m_p_start = last.a;
TRACE( 0, "Placer: pullback triggered [%d] [%s %s]",
n % last_tail.Format().c_str() % first_head.Format().c_str() );
TRACE(0, "Placer: pullback triggered [%d] [%s %s]", n % last_tail.Format().c_str() % first_head.Format().c_str()); // erase the last point in the tail, hoping that the next iteration will
// erase the last point in the tail, hoping that the next iteration will result with a head // result with a head trace that starts with a segment following our
// trace that starts with a segment following our current direction. // current direction.
if( n < 2 ) if( n < 2 )
tail.Clear(); // don't leave a single-point tail tail.Clear(); // don't leave a single-point tail
else else
@ -214,14 +213,7 @@ bool PNS_LINE_PLACER::handlePullback()
return false; return false;
} }
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a certain number
* of latest tail segments with a direct trace leading to aEnd that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
{ {
SHAPE_LINE_CHAIN& head = m_head.GetLine(); SHAPE_LINE_CHAIN& head = m_head.GetLine();
@ -247,7 +239,8 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
const SEG s = tail.CSegment( i ); const SEG s = tail.CSegment( i );
DIRECTION_45 dir( s ); DIRECTION_45 dir( s );
// calculate a replacement route and check if it matches the direction of the segment to be replaced // calculate a replacement route and check if it matches
// the direction of the segment to be replaced
SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.a, aEnd ); SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.a, aEnd );
PNS_LINE tmp( m_tail, replacement ); PNS_LINE tmp( m_tail, replacement );
@ -265,7 +258,6 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
if( reduce_index >= 0 ) if( reduce_index >= 0 )
{ {
TRACE( 0, "Placer: reducing tail: %d", reduce_index ); TRACE( 0, "Placer: reducing tail: %d", reduce_index );
SHAPE_LINE_CHAIN reducedLine = new_direction.BuildInitialTrace( new_start, aEnd ); SHAPE_LINE_CHAIN reducedLine = new_direction.BuildInitialTrace( new_start, aEnd );
@ -283,32 +275,23 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
} }
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool PNS_LINE_PLACER::checkObtusity( const SEG& a, const SEG& b ) const bool PNS_LINE_PLACER::checkObtusity( const SEG& a, const SEG& b ) const
{ {
const DIRECTION_45 dir_a( a ); const DIRECTION_45 dir_a( a );
const DIRECTION_45 dir_b( b ); const DIRECTION_45 dir_b( b );
return dir_a.IsObtuse( dir_b ) || dir_a == dir_b; return dir_a.IsObtuse( dir_b ) || dir_a == dir_b;
} }
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain conditions are met.
* @return true, if the line has been changed.
*/
bool PNS_LINE_PLACER::mergeHead() bool PNS_LINE_PLACER::mergeHead()
{ {
SHAPE_LINE_CHAIN& head = m_head.GetLine(); SHAPE_LINE_CHAIN& head = m_head.GetLine();
SHAPE_LINE_CHAIN& tail = m_tail.GetLine(); SHAPE_LINE_CHAIN& tail = m_tail.GetLine();
const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE | DIRECTION_45::ANG_HALF_FULL | DIRECTION_45::ANG_UNDEFINED; const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE |
DIRECTION_45::ANG_HALF_FULL |
DIRECTION_45::ANG_UNDEFINED;
head.Simplify(); head.Simplify();
tail.Simplify(); tail.Simplify();
@ -338,6 +321,7 @@ bool PNS_LINE_PLACER::mergeHead()
if( n_tail ) if( n_tail )
{ {
dir_tail = DIRECTION_45( tail.CSegment( -1 ) ); dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
if( dir_head.Angle( dir_tail ) & ForbiddenAngles ) if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
return false; return false;
} }
@ -357,18 +341,17 @@ bool PNS_LINE_PLACER::mergeHead()
m_p_start = last.b; m_p_start = last.b;
m_direction = DIRECTION_45( last ).Right(); m_direction = DIRECTION_45( last ).Right();
head.Remove( 0, n_head - 2 ); head.Remove( 0, n_head - 2 );
TRACE( 0, "Placer: merge %d, new direction: %s", n_head % m_direction.Format().c_str() ); TRACE( 0, "Placer: merge %d, new direction: %s", n_head % m_direction.Format().c_str() );
head.Simplify(); head.Simplify();
tail.Simplify(); tail.Simplify();
return true; return true;
} }
bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
{ {
if( !m_placingVia ) if( !m_placingVia )
@ -381,10 +364,11 @@ bool PNS_LINE_PLACER::handleViaPlacement ( PNS_LINE& aHead )
VECTOR2I force; VECTOR2I force;
VECTOR2I lead = aHead.GetCLine().CPoint( -1 ) - aHead.GetCLine().CPoint( 0 ); VECTOR2I lead = aHead.GetCLine().CPoint( -1 ) - aHead.GetCLine().CPoint( 0 );
if( v.PushoutForce( m_shove->GetCurrentNode(), lead, force, true, 20 ) ) if( v.PushoutForce( m_shove->GetCurrentNode(), lead, force, true, 20 ) )
{ {
SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace(aHead.GetCLine().CPoint(0), aHead.GetCLine().CPoint(-1) + force); SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace(
aHead.GetCLine().CPoint( 0 ),
aHead.GetCLine().CPoint( -1 ) + force );
aHead = PNS_LINE( aHead, line ); aHead = PNS_LINE( aHead, line );
v.SetPos( v.GetPos() + force ); v.SetPos( v.GetPos() + force );
@ -394,15 +378,9 @@ bool PNS_LINE_PLACER::handleViaPlacement ( PNS_LINE& aHead )
return false; return false;
} }
/**
* Function routeHead() bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead,
* bool aCwWalkaround )
* Computes the head trace between the current start point (m_p_start) and point aP,
* starting with direction defined in m_direction. The trace walks around all
* colliding solid or non-movable items. Movable segments are ignored, as they'll be handled
* later by the shove algorithm.
*/
bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround)
{ {
// STAGE 1: route a simple two-segment trace between m_p_start and aP... // STAGE 1: route a simple two-segment trace between m_p_start and aP...
SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP ); SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP );
@ -410,12 +388,12 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
PNS_LINE initTrack( m_head, line ); PNS_LINE initTrack( m_head, line );
PNS_LINE walkFull, walkSolids; PNS_LINE walkFull, walkSolids;
if( m_mode == RM_Ignore ) if( m_mode == RM_Ignore )
{ {
aNewHead = initTrack; aNewHead = initTrack;
return true; return true;
} }
handleViaPlacement( initTrack ); handleViaPlacement( initTrack );
m_currentNode = m_shove->GetCurrentNode(); m_currentNode = m_shove->GetCurrentNode();
@ -450,6 +428,7 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
// printf("nh w %d l %d\n", aNewHead.GetWidth(), aNewHead.GetLayers().Start()); // printf("nh w %d l %d\n", aNewHead.GetWidth(), aNewHead.GetLayers().Start());
return true; return true;
} }
#endif #endif
PNS_COST_ESTIMATOR cost_walk, cost_orig; PNS_COST_ESTIMATOR cost_walk, cost_orig;
@ -477,7 +456,8 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
walk_better = false; walk_better = false;
#if 0 #if 0
printf("RtTrk width %d %d %d", initTrack.GetWidth(), walkFull.GetWidth(), walkSolids.GetWidth()); printf( "RtTrk width %d %d %d", initTrack.GetWidth(),
walkFull.GetWidth(), walkSolids.GetWidth() );
printf( "init-coll %d\n", m_currentNode->CheckColliding( &initTrack ) ? 1 : 0 ); printf( "init-coll %d\n", m_currentNode->CheckColliding( &initTrack ) ? 1 : 0 );
printf( "total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n", printf( "total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n",
cost_walk.GetCornerCost(), cost_walk.GetLengthCost(), cost_walk.GetCornerCost(), cost_walk.GetLengthCost(),
@ -485,7 +465,8 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
walk_better ); walk_better );
#endif #endif
if(m_mode == RM_Smart && wf == PNS_WALKAROUND::DONE && walk_better && walkFull.GetCLine().CPoint(-1) == initTrack.GetCLine().CPoint(-1)) if( m_mode == RM_Smart && wf == PNS_WALKAROUND::DONE && walk_better
&& walkFull.GetCLine().CPoint( -1 ) == initTrack.GetCLine().CPoint( -1 ) )
l2 = walkFull; l2 = walkFull;
else if( stat_solids == PNS_WALKAROUND::DONE ) else if( stat_solids == PNS_WALKAROUND::DONE )
l2 = walkSolids; l2 = walkSolids;
@ -513,7 +494,6 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
if( status == PNS_SHOVE::SH_OK ) if( status == PNS_SHOVE::SH_OK )
{ {
optimizer.SetWorld( m_currentNode ); optimizer.SetWorld( m_currentNode );
optimizer.ClearCache(); optimizer.ClearCache();
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS ); optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
@ -523,7 +503,9 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
aNewHead = l2; aNewHead = l2;
return true; return true;
} else { }
else
{
walkaround.SetWorld( m_currentNode ); walkaround.SetWorld( m_currentNode );
walkaround.SetSolidsOnly( false ); walkaround.SetSolidsOnly( false );
walkaround.SetIterationLimit( 10 ); walkaround.SetIterationLimit( 10 );
@ -534,20 +516,12 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
return false; return false;
} }
} }
return false; return false;
} }
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by merging
* obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool PNS_LINE_PLACER::optimizeTailHeadTransition() bool PNS_LINE_PLACER::optimizeTailHeadTransition()
{ {
SHAPE_LINE_CHAIN& head = m_head.GetLine(); SHAPE_LINE_CHAIN& head = m_head.GetLine();
@ -568,12 +542,12 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
PNS_LINE new_head( m_tail, opt_line ); PNS_LINE new_head( m_tail, opt_line );
// and see if it could be made simpler by merging obtuse/collnear segments. If so, // and see if it could be made simpler by merging obtuse/collnear segments.
// replace the (threshold) last tail points and the head with the optimized line // If so, replace the (threshold) last tail points and the head with
// the optimized line
// if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS)) // if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS))
if( new_head.MergeSegments() ) if( new_head.MergeSegments() )
{ {
PNS_LINE tmp( m_tail, opt_line ); PNS_LINE tmp( m_tail, opt_line );
@ -593,14 +567,6 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
return false; return false;
} }
/**
* Function routeStep()
*
* Performs a single routing alorithm step, for the end point aP.
* @param aP ending point of current route
* @return true, if the line has been changed.
*/
void PNS_LINE_PLACER::routeStep( const VECTOR2I& aP ) void PNS_LINE_PLACER::routeStep( const VECTOR2I& aP )
{ {
@ -613,11 +579,12 @@ void PNS_LINE_PLACER::routeStep(const VECTOR2I& aP)
m_follow_mouse = true; m_follow_mouse = true;
TRACE(2,"INIT-DIR: %s head: %d, tail: %d segs\n", m_initial_direction.Format().c_str() % m_head.GetCLine().SegmentCount() % m_tail.GetCLine().SegmentCount()); TRACE( 2, "INIT-DIR: %s head: %d, tail: %d segs\n",
m_initial_direction.Format().c_str() % m_head.GetCLine().SegmentCount() %
m_tail.GetCLine().SegmentCount() );
for( i = 0; i < n_iter; i++ ) for( i = 0; i < n_iter; i++ )
{ {
if( !go_back && m_follow_mouse ) if( !go_back && m_follow_mouse )
reduceTail( aP ); reduceTail( aP );
@ -651,20 +618,12 @@ void PNS_LINE_PLACER::routeStep(const VECTOR2I& aP)
{ {
if( optimizeTailHeadTransition() ) if( optimizeTailHeadTransition() )
return; return;
mergeHead(); mergeHead();
} }
} }
/**
* Function Route()
*
* Re-routes the current track to point aP. Returns true, when routing has completed
* successfully (i.e. the trace end has reached point aP), and false if the trace was stuck somewhere
* on the way. May call routeStep() repetitively due to mouse smoothing.
* @param aP ending point of current route.
* @return true, if the routing is complete.
*/
bool PNS_LINE_PLACER::Route( const VECTOR2I& aP ) bool PNS_LINE_PLACER::Route( const VECTOR2I& aP )
{ {
if( m_smooth_mouse ) if( m_smooth_mouse )
@ -680,9 +639,9 @@ bool PNS_LINE_PLACER::Route(const VECTOR2I& aP)
p_cur += step; p_cur += step;
routeStep( p_cur ); routeStep( p_cur );
} while( p_cur != aP ); } while( p_cur != aP );
} else }
else
routeStep( aP ); routeStep( aP );
return CurrentEnd() == aP; return CurrentEnd() == aP;
@ -692,24 +651,30 @@ bool PNS_LINE_PLACER::Route(const VECTOR2I& aP)
const PNS_LINE PNS_LINE_PLACER::GetTrace() const const PNS_LINE PNS_LINE_PLACER::GetTrace() const
{ {
PNS_LINE tmp( m_head ); PNS_LINE tmp( m_head );
tmp.SetShape( m_tail.GetCLine() ); tmp.SetShape( m_tail.GetCLine() );
tmp.GetLine().Append( m_head.GetCLine() ); tmp.GetLine().Append( m_head.GetCLine() );
tmp.GetLine().Simplify(); tmp.GetLine().Simplify();
return tmp; return tmp;
} }
void PNS_LINE_PLACER::FlipPosture() void PNS_LINE_PLACER::FlipPosture()
{ {
m_initial_direction = m_initial_direction.Right(); m_initial_direction = m_initial_direction.Right();
m_direction = m_direction.Right(); m_direction = m_direction.Right();
} }
void PNS_LINE_PLACER::GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded)
void PNS_LINE_PLACER::GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
PNS_NODE::ItemVector& aAdded )
{ {
return m_shove->GetCurrentNode()->GetUpdatedItems( aRemoved, aAdded ); return m_shove->GetCurrentNode()->GetUpdatedItems( aRemoved, aAdded );
} }
PNS_NODE* PNS_LINE_PLACER::GetCurrentNode() const PNS_NODE* PNS_LINE_PLACER::GetCurrentNode() const
{ {
return m_shove->GetCurrentNode(); return m_shove->GetCurrentNode();
} }

View File

@ -39,7 +39,8 @@ class PNS_ROUTER_BASE;
/** /**
* Class PNS_LINE_PLACER * Class PNS_LINE_PLACER
* *
* Interactively routes a single track. Runs shove and walkaround algorithms when needed. * Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/ */
class PNS_LINE_PLACER class PNS_LINE_PLACER
@ -59,7 +60,16 @@ class PNS_LINE_PLACER
///> Starts placement of a line at point aStart. ///> Starts placement of a line at point aStart.
void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer ); void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer );
///> Updates the routed line with a new ending point. /**
* Function Route()
*
* Re-routes the current track to point aP. Returns true, when routing has
* completed successfully (i.e. the trace end has reached point aP), and false
* if the trace was stuck somewhere on the way. May call routeStep()
* repetitively due to mouse smoothing.
* @param aP ending point of current route.
* @return true, if the routing is complete.
*/
bool Route( const VECTOR2I& aP ); bool Route( const VECTOR2I& aP );
///> Sets initial routing direction/posture ///> Sets initial routing direction/posture
@ -67,15 +77,18 @@ class PNS_LINE_PLACER
void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings ); void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings );
///> Returns the "head" of the line being placed, that is the volatile part that has not been settled yet ///> Returns the "head" of the line being placed, that is the volatile part
///> that has not been settled yet
const PNS_LINE& GetHead() const { return m_head; } const PNS_LINE& GetHead() const { return m_head; }
///> Returns the "tail" of the line being placed the part that has been fixed already (follow mouse mode only) ///> Returns the "tail" of the line being placed the part that has been
///> fixed already (follow mouse mode only)
const PNS_LINE& GetTail() const { return m_tail; } const PNS_LINE& GetTail() const { return m_tail; }
///> Returns the whole routed line ///> Returns the whole routed line
const PNS_LINE GetTrace() const; const PNS_LINE GetTrace() const;
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions. ///> Returns the current end of the line being placed. It may not be equal
///> to the cursor position due to collisions.
const VECTOR2I& CurrentEnd() const const VECTOR2I& CurrentEnd() const
{ {
if( m_head.GetCLine().PointCount() > 0 ) if( m_head.GetCLine().PointCount() > 0 )
@ -86,10 +99,10 @@ class PNS_LINE_PLACER
return m_p_start; return m_p_start;
} }
///> Returns all items in the world that have been affected by the routing
///> Returns all items in the world that have been affected by the routing operation. Used ///> operation. Used to update data structures of the host application
/// to update data structures of the host application void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded); PNS_NODE::ItemVector& aAdded );
///> Toggles the current posture (straight/diagonal) of the trace head. ///> Toggles the current posture (straight/diagonal) of the trace head.
void FlipPosture(); void FlipPosture();
@ -98,59 +111,145 @@ class PNS_LINE_PLACER
PNS_NODE* GetCurrentNode() const; PNS_NODE* GetCurrentNode() const;
private: private:
static const double m_shoveLengthThreshold = 1.7; static const double m_shoveLengthThreshold = 1.7;
bool handleViaPlacement( PNS_LINE& aHead ); bool handleViaPlacement( PNS_LINE& aHead );
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle
* (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool checkObtusity( const SEG& a, const SEG& b ) const; bool checkObtusity( const SEG& a, const SEG& b ) const;
/**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the
* tail up to the intersecting segment and fixes the head direction to match
* the last segment before the cut.
* @return true if the line has been changed.
*/
bool handleSelfIntersections(); bool handleSelfIntersections();
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards
* wrs to the current tail direction.
* @return true if the line has been changed.
*/
bool handlePullback(); bool handlePullback();
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
bool mergeHead(); bool mergeHead();
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a
* certain number of latest tail segments with a direct trace leading to aEnd
* that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool reduceTail( const VECTOR2I& aEnd ); bool reduceTail( const VECTOR2I& aEnd );
void fixHeadPosture(); void fixHeadPosture();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool optimizeTailHeadTransition(); bool optimizeTailHeadTransition();
bool routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround = true); /**
* Function routeHead()
*
* Computes the head trace between the current start point (m_p_start) and
* point aP, starting with direction defined in m_direction. The trace walks
* around all colliding solid or non-movable items. Movable segments are
* ignored, as they'll be handled later by the shove algorithm.
*/
bool routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead,
bool aCwWalkaround = true );
/**
* Function routeStep()
*
* Performs a single routing alorithm step, for the end point aP.
* @param aP ending point of current route
* @return true, if the line has been changed.
*/
void routeStep( const VECTOR2I& aP ); void routeStep( const VECTOR2I& aP );
///> routing mode (walkaround, shove, etc.) ///> routing mode (walkaround, shove, etc.)
PNS_MODE m_mode; PNS_MODE m_mode;
///> follow mouse trail by attaching new segments to the head as the cursor moves
///> follow mouse trail by attaching new segments to the head
///> as the cursor moves
bool m_follow_mouse; bool m_follow_mouse;
///> mouse smoothing active ///> mouse smoothing active
bool m_smooth_mouse; bool m_smooth_mouse;
///> mouse smoothing step (in world units) ///> mouse smoothing step (in world units)
int m_smoothing_step; int m_smoothing_step;
///> current routing direction ///> current routing direction
DIRECTION_45 m_direction; DIRECTION_45 m_direction;
///> routing direction for new traces ///> routing direction for new traces
DIRECTION_45 m_initial_direction; DIRECTION_45 m_initial_direction;
///> routing "head": volatile part of the track from the previously ///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination /// analyzed point to the current routing destination
PNS_LINE m_head; PNS_LINE m_head;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles ///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE m_tail; PNS_LINE m_tail;
///> current algorithm iteration ///> current algorithm iteration
int m_iteration; int m_iteration;
///> pointer to world to search colliding items ///> pointer to world to search colliding items
PNS_NODE* m_world; PNS_NODE* m_world;
///> current routing start point (end of tail, beginning of head) ///> current routing start point (end of tail, beginning of head)
VECTOR2I m_p_start; VECTOR2I m_p_start;
///> The shove engine ///> The shove engine
PNS_SHOVE* m_shove; PNS_SHOVE* m_shove;
///> Current world state ///> Current world state
PNS_NODE* m_currentNode; PNS_NODE* m_currentNode;
///> Are we placing a via? ///> Are we placing a via?
bool m_placingVia; bool m_placingVia;
///> current via diameter ///> current via diameter
int m_viaDiameter; int m_viaDiameter;
///> current via drill ///> current via drill
int m_viaDrill; int m_viaDrill;
///> walkaround algorithm iteration limit ///> walkaround algorithm iteration limit
int m_walkaroundIterationLimit; int m_walkaroundIterationLimit;
///> smart pads optimizer enabled. ///> smart pads optimizer enabled.
bool m_smartPads; bool m_smartPads;
}; };
#endif // __PNS_LINE_PLACER_H #endif // __PNS_LINE_PLACER_H

View File

@ -54,6 +54,7 @@ PNS_NODE::PNS_NODE()
allocNodes.insert( this ); allocNodes.insert( this );
} }
PNS_NODE::~PNS_NODE() PNS_NODE::~PNS_NODE()
{ {
if( !m_children.empty() ) if( !m_children.empty() )
@ -70,7 +71,8 @@ PNS_NODE::~PNS_NODE()
allocNodes.erase( this ); allocNodes.erase( this );
for(PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i) for( PNS_INDEX::ItemSet::iterator i = m_index->begin();
i != m_index->end(); ++i )
if( (*i)->BelongsTo( this ) ) if( (*i)->BelongsTo( this ) )
delete *i; delete *i;
@ -98,39 +100,46 @@ int PNS_NODE::GetClearance(const PNS_ITEM *a, const PNS_ITEM *b) const
return clearance; return clearance;
} }
PNS_NODE* PNS_NODE::Branch() PNS_NODE* PNS_NODE::Branch()
{ {
PNS_NODE* child = new PNS_NODE; PNS_NODE* child = new PNS_NODE;
m_children.push_back( child ); m_children.push_back( child );
child->m_parent = this; child->m_parent = this;
child->m_clearanceFunctor = m_clearanceFunctor; child->m_clearanceFunctor = m_clearanceFunctor;
child->m_root = isRoot() ? this : m_root; child->m_root = isRoot() ? this : m_root;
// immmediate offspring of the root branch needs not copy anything. For the rest, // immmediate offspring of the root branch needs not copy anything.
// deep-copy joints, overridden item map and pointers to stored items. // For the rest, deep-copy joints, overridden item map and pointers
// to stored items.
if( !isRoot() ) if( !isRoot() )
{ {
JointMap::iterator j; JointMap::iterator j;
for(PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i) for( PNS_INDEX::ItemSet::iterator i = m_index->begin();
i != m_index->end(); ++i )
child->m_index->Add( *i ); child->m_index->Add( *i );
child->m_joints = m_joints; child->m_joints = m_joints;
child->m_override = m_override; child->m_override = m_override;
} }
TRACE(2, "%d items, %d joints, %d overrides", child->m_index->Size() % child->m_joints.size() % child->m_override.size()); TRACE( 2, "%d items, %d joints, %d overrides",
child->m_index->Size() % child->m_joints.size() % child->m_override.size() );
return child; return child;
} }
void PNS_NODE::unlinkParent() void PNS_NODE::unlinkParent()
{ {
if( isRoot() ) if( isRoot() )
return; return;
for( vector<PNS_NODE *>::iterator i = m_parent->m_children.begin(); i != m_parent->m_children.end(); ++i) for( vector<PNS_NODE*>::iterator i = m_parent->m_children.begin();
i != m_parent->m_children.end(); ++i )
{ {
if( *i == this ) if( *i == this )
{ {
@ -141,27 +150,34 @@ void PNS_NODE::unlinkParent ( )
} }
// function object that visits potential obstacles and performs the actual collision refining // function object that visits potential obstacles and performs
struct PNS_NODE::obstacleVisitor { // the actual collision refining
struct PNS_NODE::obstacleVisitor
{
///> node we are searching in (either root or a branch) ///> node we are searching in (either root or a branch)
PNS_NODE* m_node; PNS_NODE* m_node;
///> node that overrides root entries ///> node that overrides root entries
PNS_NODE* m_override; PNS_NODE* m_override;
///> list of encountered obstacles ///> list of encountered obstacles
Obstacles& m_tab; Obstacles& m_tab;
///> the item we are looking for collisions with ///> the item we are looking for collisions with
const PNS_ITEM* m_item; const PNS_ITEM* m_item;
///> acccepted kinds of colliding items (solids, vias, segments, etc...) ///> acccepted kinds of colliding items (solids, vias, segments, etc...)
int m_kindMask; int m_kindMask;
///> max number of hits ///> max number of hits
int m_limitCount; int m_limitCount;
///> number of items found so far ///> number of items found so far
int m_matchCount; int m_matchCount;
obstacleVisitor( PNS_NODE::Obstacles& aTab, obstacleVisitor( PNS_NODE::Obstacles& aTab, const PNS_ITEM* aItem,
const PNS_ITEM* aItem, int aKindMask ) :
int aKindMask ) m_tab( aTab ),
: m_tab(aTab),
m_item( aItem ), m_item( aItem ),
m_kindMask( aKindMask ), m_kindMask( aKindMask ),
m_limitCount( -1 ), m_limitCount( -1 ),
@ -183,11 +199,14 @@ struct PNS_NODE::obstacleVisitor {
{ {
if( !aItem->OfKind( m_kindMask ) ) if( !aItem->OfKind( m_kindMask ) )
return true; return true;
// check if there is a more recent branch with a newer (possibily modified) version of this item.
// check if there is a more recent branch with a newer
// (possibily modified) version of this item.
if( m_override && m_override->overrides( aItem ) ) if( m_override && m_override->overrides( aItem ) )
return true; return true;
int clearance = m_node->GetClearance( aItem, m_item ); int clearance = m_node->GetClearance( aItem, m_item );
if( !aItem->Collide( m_item, clearance ) ) if( !aItem->Collide( m_item, clearance ) )
return true; return true;
@ -200,11 +219,14 @@ struct PNS_NODE::obstacleVisitor {
if( m_limitCount > 0 && m_matchCount >= m_limitCount ) if( m_limitCount > 0 && m_matchCount >= m_limitCount )
return false; return false;
return true; return true;
}; };
}; };
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, PNS_NODE::Obstacles& aObstacles, int aKindMask, int aLimitCount)
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
PNS_NODE::Obstacles& aObstacles, int aKindMask, int aLimitCount )
{ {
obstacleVisitor visitor( aObstacles, aItem, aKindMask ); obstacleVisitor visitor( aObstacles, aItem, aKindMask );
@ -226,6 +248,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, PNS_NODE::Obstacles& aObsta
return aObstacles.size(); return aObstacles.size();
} }
PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask ) PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask )
{ {
Obstacles obs_list; Obstacles obs_list;
@ -236,6 +259,7 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
obs_list.reserve( 100 ); obs_list.reserve( 100 );
int n = 0; int n = 0;
for( int i = 0; i < line.SegmentCount(); i++ ) for( int i = 0; i < line.SegmentCount(); i++ )
{ {
const PNS_SEGMENT s( *aItem, line.CSegment( i ) ); const PNS_SEGMENT s( *aItem, line.CSegment( i ) );
@ -276,8 +300,8 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
BOOST_FOREACH( SHAPE_LINE_CHAIN::Intersection isect, isect_list ) BOOST_FOREACH( SHAPE_LINE_CHAIN::Intersection isect, isect_list )
{ {
int dist = aLine.GetCLine().Length() +
int dist = aLine.GetCLine().Length() + (isect.p - aLine.GetVia().GetPos()).EuclideanNorm(); ( isect.p - aLine.GetVia().GetPos() ).EuclideanNorm();
if( dist < nearest.dist_first ) if( dist < nearest.dist_first )
{ {
@ -302,7 +326,6 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
BOOST_FOREACH( SHAPE_LINE_CHAIN::Intersection isect, isect_list ) BOOST_FOREACH( SHAPE_LINE_CHAIN::Intersection isect, isect_list )
{ {
int dist = aLine.GetCLine().PathLength( isect.p ); int dist = aLine.GetCLine().PathLength( isect.p );
if( dist < nearest.dist_first ) if( dist < nearest.dist_first )
@ -319,7 +342,6 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
dist_max = dist; dist_max = dist;
ip_last = isect.p; ip_last = isect.p;
} }
} }
nearest.ip_last = ip_last; nearest.ip_last = ip_last;
@ -329,9 +351,11 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
return found_isects ? nearest : OptObstacle(); return found_isects ? nearest : OptObstacle();
} }
PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask ) PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask )
{ {
Obstacles obs; Obstacles obs;
obs.reserve( 100 ); obs.reserve( 100 );
if( aItemA->GetKind() == PNS_ITEM::LINE ) if( aItemA->GetKind() == PNS_ITEM::LINE )
@ -344,6 +368,7 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM *aItemA, int aKin
{ {
const PNS_SEGMENT s( *line, l.CSegment( i ) ); const PNS_SEGMENT s( *line, l.CSegment( i ) );
n += QueryColliding( &s, obs, aKindMask, 1 ); n += QueryColliding( &s, obs, aKindMask, 1 );
if( n ) if( n )
return OptObstacle( obs[0] ); return OptObstacle( obs[0] );
} }
@ -351,15 +376,18 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM *aItemA, int aKin
if( line->EndsWithVia() ) if( line->EndsWithVia() )
{ {
n += QueryColliding( &line->GetVia(), obs, aKindMask, 1 ); n += QueryColliding( &line->GetVia(), obs, aKindMask, 1 );
if( n ) if( n )
return OptObstacle( obs[0] ); return OptObstacle( obs[0] );
} }
}
} else if (QueryColliding(aItemA, obs, aKindMask, 1) > 0) else if( QueryColliding( aItemA, obs, aKindMask, 1 ) > 0 )
return OptObstacle( obs[0] ); return OptObstacle( obs[0] );
return OptObstacle(); return OptObstacle();
} }
bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, int aKindMask ) bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, int aKindMask )
{ {
Obstacles dummy; Obstacles dummy;
@ -370,33 +398,38 @@ bool PNS_NODE::CheckColliding( const PNS_ITEM *aItemA, const PNS_ITEM *aItemB, i
return aItemA->Collide( aItemB, GetClearance( aItemA, aItemB ) ); return aItemA->Collide( aItemB, GetClearance( aItemA, aItemB ) );
} }
struct hitVisitor {
struct hitVisitor
{
PNS_ITEMSET& m_items; PNS_ITEMSET& m_items;
const VECTOR2I& m_point; const VECTOR2I& m_point;
PNS_NODE* m_world; PNS_NODE* m_world;
hitVisitor( PNS_ITEMSET& aTab, hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, PNS_NODE* aWorld ) :
const VECTOR2I& aPoint, m_items( aTab ), m_point( aPoint ), m_world( aWorld ) {};
PNS_NODE *aWorld )
: m_items(aTab), m_point(aPoint), m_world(aWorld) { };
bool operator()( PNS_ITEM *aItem ) { bool operator()( PNS_ITEM* aItem )
{
SHAPE_CIRCLE cp( m_point, 0 ); SHAPE_CIRCLE cp( m_point, 0 );
int cl = 0; int cl = 0;
if( aItem->GetKind() == PNS_ITEM::SEGMENT ) if( aItem->GetKind() == PNS_ITEM::SEGMENT )
cl += static_cast<PNS_SEGMENT*>(aItem)->GetWidth() / 2; cl += static_cast<PNS_SEGMENT*>(aItem)->GetWidth() / 2;
if( aItem->GetShape()->Collide( &cp, cl ) ) if( aItem->GetShape()->Collide( &cp, cl ) )
m_items.Add( aItem ); m_items.Add( aItem );
return true; return true;
} }
}; };
const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint )
{ {
PNS_ITEMSET items; PNS_ITEMSET items;
SHAPE_CIRCLE s (aPoint, 0); // fixme: we treat a point as an infinitely small circle - this is inefficient. // fixme: we treat a point as an infinitely small circle - this is inefficient.
SHAPE_CIRCLE s( aPoint, 0 );
hitVisitor visitor( items, aPoint, this ); hitVisitor visitor( items, aPoint, this );
m_index->Query( &s, m_maxClearance, visitor ); m_index->Query( &s, m_maxClearance, visitor );
@ -417,18 +450,21 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint )
return items; return items;
} }
void PNS_NODE::addSolid( PNS_SOLID* aSolid ) void PNS_NODE::addSolid( PNS_SOLID* aSolid )
{ {
linkJoint( aSolid->GetCenter(), aSolid->GetLayers(), aSolid->GetNet(), aSolid ); linkJoint( aSolid->GetCenter(), aSolid->GetLayers(), aSolid->GetNet(), aSolid );
m_index->Add( aSolid ); m_index->Add( aSolid );
} }
void PNS_NODE::addVia( PNS_VIA* aVia ) void PNS_NODE::addVia( PNS_VIA* aVia )
{ {
linkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia ); linkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia );
m_index->Add( aVia ); m_index->Add( aVia );
} }
void PNS_NODE::addLine( PNS_LINE* aLine ) void PNS_NODE::addLine( PNS_LINE* aLine )
{ {
const SHAPE_LINE_CHAIN& l = aLine->GetLine(); const SHAPE_LINE_CHAIN& l = aLine->GetLine();
@ -453,6 +489,7 @@ void PNS_NODE::addLine( PNS_LINE *aLine )
} }
} }
void PNS_NODE::addSegment( PNS_SEGMENT* aSeg ) void PNS_NODE::addSegment( PNS_SEGMENT* aSeg )
{ {
if( aSeg->GetSeg().a == aSeg->GetSeg().b ) if( aSeg->GetSeg().a == aSeg->GetSeg().b )
@ -469,9 +506,9 @@ void PNS_NODE::addSegment( PNS_SEGMENT *aSeg )
m_index->Add( aSeg ); m_index->Add( aSeg );
} }
void PNS_NODE::Add( PNS_ITEM* aItem ) void PNS_NODE::Add( PNS_ITEM* aItem )
{ {
aItem->SetOwner( this ); aItem->SetOwner( this );
switch( aItem->GetKind() ) switch( aItem->GetKind() )
@ -500,11 +537,13 @@ void PNS_NODE::Add(PNS_ITEM* aItem)
void PNS_NODE::doRemove( PNS_ITEM* aItem ) void PNS_NODE::doRemove( PNS_ITEM* aItem )
{ {
// case 1: removing an item that is stored in the root node from any branch: mark it as overridden, but do not remove // case 1: removing an item that is stored in the root node from any branch:
// mark it as overridden, but do not remove
if( aItem->BelongsTo( m_root ) && !isRoot() ) if( aItem->BelongsTo( m_root ) && !isRoot() )
m_override.insert( aItem ); m_override.insert( aItem );
// case 2: the item belongs to this branch or a parent, non-root branch, or the root itself and we are the root: remove from the index // case 2: the item belongs to this branch or a parent, non-root branch,
// or the root itself and we are the root: remove from the index
else if( !aItem->BelongsTo( m_root ) || isRoot() ) else if( !aItem->BelongsTo( m_root ) || isRoot() )
m_index->Remove( aItem ); m_index->Remove( aItem );
@ -513,6 +552,7 @@ void PNS_NODE::doRemove ( PNS_ITEM *aItem )
aItem->SetOwner( NULL ); aItem->SetOwner( NULL );
} }
void PNS_NODE::removeSegment( PNS_SEGMENT* aSeg ) void PNS_NODE::removeSegment( PNS_SEGMENT* aSeg )
{ {
unlinkJoint( aSeg->GetSeg().a, aSeg->GetLayers(), aSeg->GetNet(), aSeg ); unlinkJoint( aSeg->GetSeg().a, aSeg->GetLayers(), aSeg->GetNet(), aSeg );
@ -521,6 +561,7 @@ void PNS_NODE::removeSegment (PNS_SEGMENT *aSeg )
doRemove( aSeg ); doRemove( aSeg );
} }
void PNS_NODE::removeLine( PNS_LINE* aLine ) void PNS_NODE::removeLine( PNS_LINE* aLine )
{ {
vector<PNS_SEGMENT*>* segRefs = aLine->GetLinkedSegments(); vector<PNS_SEGMENT*>* segRefs = aLine->GetLinkedSegments();
@ -538,6 +579,7 @@ void PNS_NODE::removeLine( PNS_LINE *aLine )
aLine->SetOwner( NULL ); aLine->SetOwner( NULL );
} }
void PNS_NODE::removeVia( PNS_VIA* aVia ) void PNS_NODE::removeVia( PNS_VIA* aVia )
{ {
unlinkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia ); unlinkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia );
@ -545,26 +587,30 @@ void PNS_NODE::removeVia ( PNS_VIA *aVia )
doRemove( aVia ); doRemove( aVia );
} }
void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
{ {
Remove( aOldItem ); Remove( aOldItem );
Add( aNewItem ); Add( aNewItem );
} }
void PNS_NODE::Remove( PNS_ITEM* aItem ) void PNS_NODE::Remove( PNS_ITEM* aItem )
{ {
switch( aItem->GetKind() ) switch( aItem->GetKind() )
{ {
case PNS_ITEM::SOLID: case PNS_ITEM::SOLID:
assert( false ); assert( false );
break; break;
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
removeSegment( static_cast<PNS_SEGMENT*>( aItem ) ); removeSegment( static_cast<PNS_SEGMENT*>( aItem ) );
break; break;
case PNS_ITEM::LINE: case PNS_ITEM::LINE:
removeLine( static_cast<PNS_LINE*>( aItem ) ); removeLine( static_cast<PNS_LINE*>( aItem ) );
break; break;
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
removeVia( static_cast<PNS_VIA*>( aItem ) ); removeVia( static_cast<PNS_VIA*>( aItem ) );
break; break;
@ -574,13 +620,16 @@ void PNS_NODE::Remove(PNS_ITEM *aItem)
} }
} }
void PNS_NODE::followLine(PNS_SEGMENT *current, bool scanDirection, int& pos, int limit, VECTOR2I *corners, PNS_SEGMENT **segments)
void PNS_NODE::followLine( PNS_SEGMENT* current, bool scanDirection, int& pos,
int limit, VECTOR2I* corners, PNS_SEGMENT** segments )
{ {
bool prevReversed = false; bool prevReversed = false;
for( ; ; ) for( ; ; )
{ {
const VECTOR2I p = (scanDirection ^ prevReversed) ? current->GetSeg().b : current->GetSeg().a; const VECTOR2I p =
(scanDirection ^ prevReversed) ? current->GetSeg().b : current->GetSeg().a;
const OptJoint jt = FindJoint( p, current->GetLayer(), current->GetNet() ); const OptJoint jt = FindJoint( p, current->GetLayer(), current->GetNet() );
assert( jt ); assert( jt );
@ -595,10 +644,12 @@ void PNS_NODE::followLine(PNS_SEGMENT *current, bool scanDirection, int& pos, in
break; break;
current = jt->NextSegment( current ); current = jt->NextSegment( current );
prevReversed = (jt->GetPos() == (scanDirection ? current->GetSeg().b : current->GetSeg().a )); prevReversed =
( jt->GetPos() == (scanDirection ? current->GetSeg().b : current->GetSeg().a ) );
} }
} }
PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, const OptJoint& a, const OptJoint& b ) PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, const OptJoint& a, const OptJoint& b )
{ {
const int MaxVerts = 1024; const int MaxVerts = 1024;
@ -621,6 +672,7 @@ PNS_LINE *PNS_NODE::AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a, const Opt
int clip_start = -1, clip_end = -1; int clip_start = -1, clip_end = -1;
for( int i = i_start + 1; i < i_end; i++ ) for( int i = i_start + 1; i < i_end; i++ )
{ {
const VECTOR2I& p = corners[i]; const VECTOR2I& p = corners[i];
@ -632,6 +684,7 @@ PNS_LINE *PNS_NODE::AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a, const Opt
} }
pl->GetLine().Append( p ); pl->GetLine().Append( p );
if( segs[i - 1] != segs[i] ) if( segs[i - 1] != segs[i] )
pl->LinkSegment( segs[i] ); pl->LinkSegment( segs[i] );
} }
@ -639,6 +692,7 @@ PNS_LINE *PNS_NODE::AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a, const Opt
return pl; return pl;
} }
void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ) void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b )
{ {
a = *FindJoint( aLine->GetCLine().CPoint( 0 ), aLine->GetLayers().Start(), aLine->GetNet() ); a = *FindJoint( aLine->GetCLine().CPoint( 0 ), aLine->GetLayers().Start(), aLine->GetNet() );
@ -657,15 +711,18 @@ int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, vector<PNS_LIN
PNS_JOINT j_start, j_end; PNS_JOINT j_start, j_end;
FindLineEnds( line, j_start, j_end ); FindLineEnds( line, j_start, j_end );
if( (j_start == a && j_end == b )|| (j_end == a && j_start == b) ) if( (j_start == a && j_end == b )|| (j_end == a && j_start == b) )
aLines.push_back( line ); aLines.push_back( line );
else else
delete line; delete line;
} }
} }
return 0; return 0;
} }
const PNS_NODE::OptJoint PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ) const PNS_NODE::OptJoint PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
{ {
PNS_JOINT::HashTag tag; PNS_JOINT::HashTag tag;
@ -688,11 +745,14 @@ const PNS_NODE::OptJoint PNS_NODE::FindJoint(const VECTOR2I &aPos, int aLayer, i
{ {
if( f->second.GetLayers().Overlaps( aLayer ) ) if( f->second.GetLayers().Overlaps( aLayer ) )
return f->second; return f->second;
++f; ++f;
} }
return OptJoint(); return OptJoint();
} }
PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet ) PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet )
{ {
PNS_JOINT::HashTag tag; PNS_JOINT::HashTag tag;
@ -709,6 +769,7 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye
if( f == m_joints.end() && !isRoot() ) if( f == m_joints.end() && !isRoot() )
{ {
range = m_root->m_joints.equal_range( tag ); range = m_root->m_joints.equal_range( tag );
for( f = range.first; f != range.second; ++f ) for( f = range.first; f != range.second; ++f )
m_joints.insert( *f ); m_joints.insert( *f );
} }
@ -741,22 +802,31 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye
return m_joints.insert( TagJointPair( tag, jt ) )->second; return m_joints.insert( TagJointPair( tag, jt ) )->second;
} }
void PNS_JOINT::Dump() const void PNS_JOINT::Dump() const
{ {
printf("joint layers %d-%d, net %d, pos %s, links: %d\n", m_layers.Start(), m_layers.End(), m_tag.net, m_tag.pos.Format().c_str(), LinkCount() ); printf( "joint layers %d-%d, net %d, pos %s, links: %d\n", m_layers.Start(),
m_layers.End(), m_tag.net, m_tag.pos.Format().c_str(), LinkCount() );
} }
void PNS_NODE::linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere ) void PNS_NODE::linkJoint( const VECTOR2I& aPos,
const PNS_LAYERSET& aLayers,
int aNet,
PNS_ITEM* aWhere )
{ {
PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet ); PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet );
jt.Link( aWhere ); jt.Link( aWhere );
} }
void PNS_NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere )
void PNS_NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet, PNS_ITEM* aWhere )
{ {
// fixme: remove dangling joints // fixme: remove dangling joints
PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet ); PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet );
jt.Unlink( aWhere ); jt.Unlink( aWhere );
} }
@ -780,13 +850,15 @@ void PNS_NODE::Dump(bool aLong)
all_segs.insert( static_cast<PNS_SEGMENT*>(*i) ); all_segs.insert( static_cast<PNS_SEGMENT*>(*i) );
} }
JointMap::iterator j; JointMap::iterator j;
if( aLong ) if( aLong )
for( j = m_joints.begin(); j!=m_joints.end(); ++j ) for( j = m_joints.begin(); j!=m_joints.end(); ++j )
{ {
printf("joint : %s, links : %d\n", j->second.GetPos().Format().c_str(), j->second.LinkCount()); printf( "joint : %s, links : %d\n",
j->second.GetPos().Format().c_str(), j->second.LinkCount() );
PNS_JOINT::LinkedItems::const_iterator k; PNS_JOINT::LinkedItems::const_iterator k;
for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k ) for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
{ {
const PNS_ITEM* item = *k; const PNS_ITEM* item = *k;
@ -796,16 +868,21 @@ void PNS_NODE::Dump(bool aLong)
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
{ {
const PNS_SEGMENT* seg = static_cast<const PNS_SEGMENT*>(item); const PNS_SEGMENT* seg = static_cast<const PNS_SEGMENT*>(item);
printf(" -> seg %s %s\n", seg->GetSeg().a.Format().c_str(), seg->GetSeg().b.Format().c_str()); printf( " -> seg %s %s\n", seg->GetSeg().a.Format().c_str(),
seg->GetSeg().b.Format().c_str() );
break; break;
} }
default: default:
break; break;
} }
} }
} }
int lines_count = 0; int lines_count = 0;
while( !all_segs.empty() ) while( !all_segs.empty() )
{ {
PNS_SEGMENT* s = *all_segs.begin(); PNS_SEGMENT* s = *all_segs.begin();
@ -820,10 +897,13 @@ void PNS_NODE::Dump(bool aLong)
for( vector<PNS_SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j ) for( vector<PNS_SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j )
{ {
printf( "%s ", (*j)->GetSeg().a.Format().c_str() ); printf( "%s ", (*j)->GetSeg().a.Format().c_str() );
if( j + 1 == seg_refs->end() ) if( j + 1 == seg_refs->end() )
printf( "%s\n", (*j)->GetSeg().b.Format().c_str() ); printf( "%s\n", (*j)->GetSeg().b.Format().c_str() );
all_segs.erase( *j ); all_segs.erase( *j );
} }
lines_count++; lines_count++;
} }
@ -831,6 +911,7 @@ void PNS_NODE::Dump(bool aLong)
#endif #endif
} }
void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ) void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded )
{ {
aRemoved.reserve( m_override.size() ); aRemoved.reserve( m_override.size() );
@ -846,33 +927,35 @@ void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded)
aAdded.push_back( *i ); aAdded.push_back( *i );
} }
void PNS_NODE::releaseChildren() void PNS_NODE::releaseChildren()
{ {
// copy the kids as the PNS_NODE destructor erases the item from the parent node. // copy the kids as the PNS_NODE destructor erases the item from the parent node.
vector<PNS_NODE*> kids = m_children; vector<PNS_NODE*> kids = m_children;
BOOST_FOREACH(PNS_NODE *node, kids) BOOST_FOREACH( PNS_NODE * node, kids ) {
{
node->releaseChildren(); node->releaseChildren();
delete node; delete node;
} }
} }
void PNS_NODE::Commit( PNS_NODE* aNode ) void PNS_NODE::Commit( PNS_NODE* aNode )
{ {
if( aNode->isRoot() ) if( aNode->isRoot() )
return; return;
BOOST_FOREACH( PNS_ITEM * item, aNode->m_override ) BOOST_FOREACH( PNS_ITEM * item, aNode->m_override )
Remove( item ); Remove( item );
for(PNS_INDEX::ItemSet::iterator i = aNode->m_index->begin(); i!= aNode ->m_index->end(); ++i) for( PNS_INDEX::ItemSet::iterator i = aNode->m_index->begin();
i != aNode->m_index->end(); ++i )
Add( *i ); Add( *i );
releaseChildren(); releaseChildren();
} }
void PNS_NODE::KillChildren() void PNS_NODE::KillChildren()
{ {
assert( isRoot() ); assert( isRoot() );
@ -881,7 +964,6 @@ void PNS_NODE::KillChildren()
} }
void PNS_NODE::AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems ) void PNS_NODE::AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems )
{ {
PNS_INDEX::NetItemsList* l_cur = m_index->GetItemsForNet( aNet ); PNS_INDEX::NetItemsList* l_cur = m_index->GetItemsForNet( aNet );
@ -890,6 +972,7 @@ void PNS_NODE::AllItemsInNet ( int aNet, std::list<PNS_ITEM *>& aItems)
return; return;
std::copy( aItems.begin(), l_cur->begin(), l_cur->end() ); std::copy( aItems.begin(), l_cur->begin(), l_cur->end() );
if( !isRoot() ) if( !isRoot() )
{ {
PNS_INDEX::NetItemsList* l_root = m_root->m_index->GetItemsForNet( aNet ); PNS_INDEX::NetItemsList* l_root = m_root->m_index->GetItemsForNet( aNet );
@ -897,5 +980,8 @@ void PNS_NODE::AllItemsInNet ( int aNet, std::list<PNS_ITEM *>& aItems)
for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i ) for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i )
if( !overrides( *i ) ) if( !overrides( *i ) )
aItems.push_back( *i ); aItems.push_back( *i );
} }
} }

View File

@ -45,7 +45,8 @@ class PNS_INDEX;
using boost::shared_ptr; using boost::shared_ptr;
class PNS_CLEARANCE_FUNC { class PNS_CLEARANCE_FUNC
{
public: public:
virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0; virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0;
}; };
@ -67,8 +68,8 @@ struct PNS_OBSTACLE
///> Hull of the colliding item ///> Hull of the colliding item
SHAPE_LINE_CHAIN hull; SHAPE_LINE_CHAIN hull;
///> First and last intersection point between the head item and the hull of the ///> First and last intersection point between the head item and the hull
//// colliding item ///> of the colliding item
VECTOR2I ip_first, ip_last; VECTOR2I ip_first, ip_last;
///> ... and the distance thereof ///> ... and the distance thereof
@ -78,18 +79,19 @@ struct PNS_OBSTACLE
/** /**
* Class PNS_NODE * Class PNS_NODE
* *
* Keeps the router "world" - i.e. all the tracks, vias, solids in a hierarchical and indexed way. * Keeps the router "world" - i.e. all the tracks, vias, solids in a
* hierarchical and indexed way.
* Features: * Features:
* - spatial-indexed container for PCB item shapes * - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking) * - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths * - assembly of lines connecting joints, finding loops and unique paths
* - lightweight cloning/branching (for recursive optimization and shove springback) * - lightweight cloning/branching (for recursive optimization and shove
* springback)
**/ **/
class PNS_NODE { class PNS_NODE
{
public: public:
typedef boost::optional<PNS_OBSTACLE> OptObstacle; typedef boost::optional<PNS_OBSTACLE> OptObstacle;
typedef std::vector<PNS_ITEM*> ItemVector; typedef std::vector<PNS_ITEM*> ItemVector;
typedef std::vector<PNS_OBSTACLE> Obstacles; typedef std::vector<PNS_OBSTACLE> Obstacles;
@ -117,17 +119,24 @@ public:
m_clearanceFunctor = aFunc; m_clearanceFunctor = aFunc;
} }
///> Finds items that collide with aItem and stores collision information in aObstacles. ///> Finds items that collide with aItem and stores collision information
int QueryColliding( const PNS_ITEM* aItem, Obstacles& aObstacles, int aKindMask = PNS_ITEM::ANY, int aLimitCount = -1); ///> in aObstacles.
int QueryColliding( const PNS_ITEM* aItem,
Obstacles& aObstacles,
int aKindMask = PNS_ITEM::ANY,
int aLimitCount = -1 );
///> Finds the nearest item that collides with aItem. ///> Finds the nearest item that collides with aItem.
OptObstacle NearestObstacle( const PNS_LINE* aItem, int aKindMask = PNS_ITEM::ANY ); OptObstacle NearestObstacle( const PNS_LINE* aItem, int aKindMask = PNS_ITEM::ANY );
///> Checks if the item collides with anything else in the world, and returns it if so. ///> Checks if the item collides with anything else in the world,
///> and returns it if so.
OptObstacle CheckColliding( const PNS_ITEM* aItem, int aKindMask = PNS_ITEM::ANY ); OptObstacle CheckColliding( const PNS_ITEM* aItem, int aKindMask = PNS_ITEM::ANY );
///> Checks if two items collide [deprecated]. ///> Checks if two items collide [deprecated].
bool CheckColliding( const PNS_ITEM *aItemA, const PNS_ITEM *aItemB, int aKindMask = PNS_ITEM::ANY); bool CheckColliding( const PNS_ITEM* aItemA,
const PNS_ITEM* aItemB,
int aKindMask = PNS_ITEM::ANY );
///> Hit detection ///> Hit detection
const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ); const PNS_ITEMSET HitTest( const VECTOR2I& aPoint );
@ -136,12 +145,14 @@ public:
void Remove( PNS_ITEM* aItem ); void Remove( PNS_ITEM* aItem );
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
///> Creates a lightweight copy ("branch") of self. Note that if there are any branches ///> Creates a lightweight copy ("branch") of self. Note that if there are
/// in use, their parents must NOT be deleted. ///> any branches in use, their parents must NOT be deleted.
PNS_NODE* Branch(); PNS_NODE* Branch();
///> Assembles a line connecting two non-trivial joints the segment aSeg belongs to. ///> Assembles a line connecting two non-trivial joints the
PNS_LINE *AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint()); ///> segment aSeg belongs to.
PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg,
const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() );
///> Dumps the contents and joints structure ///> Dumps the contents and joints structure
void Dump( bool aLong = false ); void Dump( bool aLong = false );
@ -152,8 +163,8 @@ public:
return m_joints.size(); return m_joints.size();
} }
///> Returns the lists of items removed and added in this branch, with respect ///> Returns the lists of items removed and added in this branch, with
///> to the root. ///> respect to the root.
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded ); void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded );
///> Copies the changes from a given branch (aNode) to the root. Called on ///> Copies the changes from a given branch (aNode) to the root. Called on
@ -164,13 +175,16 @@ public:
const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ); const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
///> finds all linest between a pair of joints. Used by the loop removal engine. ///> finds all linest between a pair of joints. Used by the loop removal engine.
int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector<PNS_LINE *> &aLines ); int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b,
std::vector<PNS_LINE*>& aLines );
///> finds the joints corresponding to the ends of line aLine ///> finds the joints corresponding to the ends of line aLine
void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ); void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b );
///> finds all joints that have an (in)direct connection(s) (i.e. segments/vias) with the joint aJoint. ///> finds all joints that have an (in)direct connection(s)
void FindConnectedJoints( const PNS_JOINT& aJoint, std::vector<PNS_JOINT *> &aConnectedJoints ); ///> (i.e. segments/vias) with the joint aJoint.
void FindConnectedJoints( const PNS_JOINT& aJoint,
std::vector<PNS_JOINT*>& aConnectedJoints );
///> Destroys all child nodes. Applicable only to the root node. ///> Destroys all child nodes. Applicable only to the root node.
void KillChildren(); void KillChildren();
@ -178,7 +192,6 @@ public:
void AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems ); void AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems );
private: private:
struct obstacleVisitor; struct obstacleVisitor;
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap; typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap;
typedef JointMap::value_type TagJointPair; typedef JointMap::value_type TagJointPair;
@ -188,16 +201,18 @@ private:
PNS_NODE& operator=( const PNS_NODE& b ); PNS_NODE& operator=( const PNS_NODE& b );
///> tries to find matching joint and creates a new one if not found ///> tries to find matching joint and creates a new one if not found
PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet ); PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet );
///> touches a joint and links it to an item ///> touches a joint and links it to an item
void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere ); void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet, PNS_ITEM* aWhere );
///> unlinks an item from a joint ///> unlinks an item from a joint
void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere ); void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet, PNS_ITEM* aWhere );
///> helpers for adding/removing items ///> helpers for adding/removing items
void addSolid( PNS_SOLID* aSeg ); void addSolid( PNS_SOLID* aSeg );
void addSegment( PNS_SEGMENT* aSeg ); void addSegment( PNS_SEGMENT* aSeg );
void addLine( PNS_LINE* aLine ); void addLine( PNS_LINE* aLine );
@ -216,20 +231,26 @@ private:
return m_parent == NULL; return m_parent == NULL;
} }
///> checks if this branch contains an updated version of the item from the root branch. ///> checks if this branch contains an updated version of the item
///> from the root branch.
bool overrides( PNS_ITEM* aItem ) const bool overrides( PNS_ITEM* aItem ) const
{ {
return m_override.find( aItem ) != m_override.end(); return m_override.find( aItem ) != m_override.end();
} }
///> scans the joint map, forming a line starting from segment (current). ///> scans the joint map, forming a line starting from segment (current).
void followLine(PNS_SEGMENT *current, bool scanDirection, int& pos, int limit, VECTOR2I *corners, PNS_SEGMENT **segments); void followLine( PNS_SEGMENT* current,
bool scanDirection,
int& pos,
int limit,
VECTOR2I* corners,
PNS_SEGMENT** segments );
///> spatial index of all items ///> spatial index of all items
// SHAPE_INDEX_LIST<PNS_ITEM *> m_items; // SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
///> hash table with the joints, linking the items. Joints are hashed by their ///> hash table with the joints, linking the items. Joints are hashed by
///> position, layer set and net. ///> their position, layer set and net.
JointMap m_joints; JointMap m_joints;
///> node this node was branched from ///> node this node was branched from

View File

@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
@ -27,13 +28,12 @@
#include "pns_optimizer.h" #include "pns_optimizer.h"
#include "pns_utils.h" #include "pns_utils.h"
using namespace std; using namespace std;
/** /**
*
Cost Estimator Methods * Cost Estimator Methods
*
**/ **/
int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b ) int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b )
@ -44,24 +44,32 @@ int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b)
{ {
case DIRECTION_45::ANG_OBTUSE: case DIRECTION_45::ANG_OBTUSE:
return 1; return 1;
case DIRECTION_45::ANG_STRAIGHT: case DIRECTION_45::ANG_STRAIGHT:
return 0; return 0;
case DIRECTION_45::ANG_ACUTE: case DIRECTION_45::ANG_ACUTE:
return 50; return 50;
case DIRECTION_45::ANG_RIGHT: case DIRECTION_45::ANG_RIGHT:
return 30; return 30;
case DIRECTION_45::ANG_HALF_FULL: case DIRECTION_45::ANG_HALF_FULL:
return 60; return 60;
default: default:
return 100; return 100;
} }
} }
int PNS_COST_ESTIMATOR::CornerCost( const SHAPE_LINE_CHAIN& aLine ) int PNS_COST_ESTIMATOR::CornerCost( const SHAPE_LINE_CHAIN& aLine )
{ {
int total = 0; int total = 0;
for( int i = 0; i < aLine.SegmentCount() - 1; ++i ) for( int i = 0; i < aLine.SegmentCount() - 1; ++i )
total += CornerCost( aLine.CSegment( i ), aLine.CSegment( i + 1 ) ); total += CornerCost( aLine.CSegment( i ), aLine.CSegment( i + 1 ) );
return total; return total;
} }
@ -71,18 +79,21 @@ int PNS_COST_ESTIMATOR::CornerCost ( const PNS_LINE& aLine )
return CornerCost( aLine.GetCLine() ); return CornerCost( aLine.GetCLine() );
} }
void PNS_COST_ESTIMATOR::Add( PNS_LINE& aLine ) void PNS_COST_ESTIMATOR::Add( PNS_LINE& aLine )
{ {
m_lengthCost += aLine.GetCLine().Length(); m_lengthCost += aLine.GetCLine().Length();
m_cornerCost += CornerCost( aLine ); m_cornerCost += CornerCost( aLine );
} }
void PNS_COST_ESTIMATOR::Remove( PNS_LINE& aLine ) void PNS_COST_ESTIMATOR::Remove( PNS_LINE& aLine )
{ {
m_lengthCost -= aLine.GetCLine().Length(); m_lengthCost -= aLine.GetCLine().Length();
m_cornerCost -= CornerCost( aLine ); m_cornerCost -= CornerCost( aLine );
} }
void PNS_COST_ESTIMATOR::Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine ) void PNS_COST_ESTIMATOR::Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine )
{ {
m_lengthCost -= aOldLine.GetCLine().Length(); m_lengthCost -= aOldLine.GetCLine().Length();
@ -92,11 +103,15 @@ void PNS_COST_ESTIMATOR::Replace(PNS_LINE &aOldLine, PNS_LINE& aNewLine)
} }
bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance, double aCornerTollerance ) const bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther,
double aLengthTollerance,
double aCornerTollerance ) const
{ {
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost ) if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
return true; return true;
else if(aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost < m_lengthCost * aLengthTollerance)
else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost <
m_lengthCost * aLengthTollerance )
return true; return true;
return false; return false;
@ -104,12 +119,10 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTol
/** /**
*
Optimizer * Optimizer
*
**/ **/
PNS_OPTIMIZER::PNS_OPTIMIZER( PNS_NODE* aWorld ) : PNS_OPTIMIZER::PNS_OPTIMIZER( PNS_NODE* aWorld ) :
m_world( aWorld ), m_collisionKindMask( PNS_ITEM::ANY ), m_effortLevel( MERGE_SEGMENTS ) m_world( aWorld ), m_collisionKindMask( PNS_ITEM::ANY ), m_effortLevel( MERGE_SEGMENTS )
{ {
@ -125,7 +138,6 @@ PNS_OPTIMIZER::~PNS_OPTIMIZER ( )
struct PNS_OPTIMIZER::CacheVisitor struct PNS_OPTIMIZER::CacheVisitor
{ {
CacheVisitor( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) : CacheVisitor( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) :
m_ourItem( aOurItem ), m_ourItem( aOurItem ),
m_collidingItem( NULL ), m_collidingItem( NULL ),
@ -153,6 +165,7 @@ struct PNS_OPTIMIZER::CacheVisitor
int m_mask; int m_mask;
}; };
void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false ) void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false )
{ {
if( m_cacheTags.find( aItem ) != m_cacheTags.end() ) if( m_cacheTags.find( aItem ) != m_cacheTags.end() )
@ -163,6 +176,7 @@ void PNS_OPTIMIZER::cacheAdd( PNS_ITEM *aItem, bool aIsStatic = false)
m_cacheTags[aItem].isStatic = aIsStatic; m_cacheTags[aItem].isStatic = aIsStatic;
} }
void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex ) void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex )
{ {
std::vector<PNS_SEGMENT*>* segs = aLine->GetLinkedSegments(); std::vector<PNS_SEGMENT*>* segs = aLine->GetLinkedSegments();
@ -181,17 +195,20 @@ void PNS_OPTIMIZER::removeCachedSegments (PNS_LINE *aLine, int aStartVertex, int
} // *cacheRemove( (*segs)[i] ); } // *cacheRemove( (*segs)[i] );
} }
void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem ) void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem )
{ {
if( aItem->GetKind() == PNS_ITEM::LINE ) if( aItem->GetKind() == PNS_ITEM::LINE )
removeCachedSegments( static_cast<PNS_LINE*> (aItem) ); removeCachedSegments( static_cast<PNS_LINE*> (aItem) );
} }
void PNS_OPTIMIZER::CacheStaticItem( PNS_ITEM* aItem ) void PNS_OPTIMIZER::CacheStaticItem( PNS_ITEM* aItem )
{ {
cacheAdd( aItem, true ); cacheAdd( aItem, true );
} }
void PNS_OPTIMIZER::ClearCache( bool aStaticOnly ) void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
{ {
if( !aStaticOnly ) if( !aStaticOnly )
@ -211,6 +228,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
} }
} }
bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache ) bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache )
{ {
CacheVisitor v( aItem, m_world, m_collisionKindMask ); CacheVisitor v( aItem, m_world, m_collisionKindMask );
@ -224,13 +242,16 @@ bool PNS_OPTIMIZER::checkColliding ( PNS_ITEM *aItem, bool aUpdateCache )
{ {
PNS_NODE::OptObstacle obs = m_world->CheckColliding( aItem ); PNS_NODE::OptObstacle obs = m_world->CheckColliding( aItem );
if(obs) { if( obs )
{
if( aUpdateCache ) if( aUpdateCache )
cacheAdd( obs->item ); cacheAdd( obs->item );
return true; return true;
} }
} else { }
else
{
m_cacheTags[v.m_collidingItem].hits++; m_cacheTags[v.m_collidingItem].hits++;
return true; return true;
} }
@ -238,12 +259,15 @@ bool PNS_OPTIMIZER::checkColliding ( PNS_ITEM *aItem, bool aUpdateCache )
return false; return false;
} }
bool PNS_OPTIMIZER::checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath ) bool PNS_OPTIMIZER::checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath )
{ {
PNS_LINE tmp( *aLine, aOptPath ); PNS_LINE tmp( *aLine, aOptPath );
return checkColliding( &tmp ); return checkColliding( &tmp );
} }
bool PNS_OPTIMIZER::mergeObtuse( PNS_LINE* aLine ) bool PNS_OPTIMIZER::mergeObtuse( PNS_LINE* aLine )
{ {
SHAPE_LINE_CHAIN& line = aLine->GetLine(); SHAPE_LINE_CHAIN& line = aLine->GetLine();
@ -262,6 +286,7 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
iter++; iter++;
int n_segs = current_path.SegmentCount(); int n_segs = current_path.SegmentCount();
int max_step = n_segs - 2; int max_step = n_segs - 2;
if( step > max_step ) if( step > max_step )
step = max_step; step = max_step;
@ -288,7 +313,9 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
{ {
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} else { }
else
{
s1opt = SEG( s1.a, ip ); s1opt = SEG( s1.a, ip );
s2opt = SEG( ip, s2.b ); s2opt = SEG( ip, s2.b );
} }
@ -313,6 +340,7 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
} }
} }
} }
n++; n++;
} }
@ -323,9 +351,11 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
line = current_path; line = current_path;
return line.SegmentCount() < segs_pre; return line.SegmentCount() < segs_pre;
} }
step--; step--;
} }
} }
return line.SegmentCount() < segs_pre; return line.SegmentCount() < segs_pre;
} }
@ -359,8 +389,6 @@ bool PNS_OPTIMIZER::mergeFull(PNS_LINE *aLine)
if( !found_anything ) if( !found_anything )
step--; step--;
} }
aLine->SetShape( current_path ); aLine->SetShape( current_path );
@ -368,6 +396,7 @@ bool PNS_OPTIMIZER::mergeFull(PNS_LINE *aLine)
return current_path.SegmentCount() < segs_pre; return current_path.SegmentCount() < segs_pre;
} }
bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult, int aStartVertex, int aEndVertex ) bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult, int aStartVertex, int aEndVertex )
{ {
if( !aResult ) if( !aResult )
@ -378,10 +407,13 @@ bool PNS_OPTIMIZER::Optimize ( PNS_LINE *aLine, PNS_LINE *aResult , int aStartVe
m_keepPostures = false; m_keepPostures = false;
bool rv = false; bool rv = false;
if( m_effortLevel & MERGE_SEGMENTS ) if( m_effortLevel & MERGE_SEGMENTS )
rv |= mergeFull( aResult ); rv |= mergeFull( aResult );
if( m_effortLevel & MERGE_OBTUSE ) if( m_effortLevel & MERGE_OBTUSE )
rv |= mergeObtuse( aResult ); rv |= mergeObtuse( aResult );
if( m_effortLevel & SMART_PADS ) if( m_effortLevel & SMART_PADS )
rv |= runSmartPads( aResult ); rv |= runSmartPads( aResult );
@ -443,13 +475,16 @@ bool PNS_OPTIMIZER::mergeStep ( PNS_LINE *aLine, SHAPE_LINE_CHAIN& aCurrentPath,
aCurrentPath = *picked; aCurrentPath = *picked;
return true; return true;
} }
n++; n++;
} }
return false; return false;
} }
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth, const SHAPE *aShape, bool aPermitDiagonal ) const
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth,
const SHAPE* aShape, bool aPermitDiagonal ) const
{ {
BreakoutList breakouts; BreakoutList breakouts;
@ -463,11 +498,13 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth, const SH
l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) ); l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) );
breakouts.push_back( l ); breakouts.push_back( l );
} }
return breakouts; return breakouts;
} }
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAPE *aShape, bool aPermitDiagonal ) const PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
const SHAPE* aShape, bool aPermitDiagonal ) const
{ {
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(aShape); const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(aShape);
VECTOR2I s = rect->GetSize(), c = rect->GetPosition() + VECTOR2I( s.x / 2, s.y / 2 ); VECTOR2I s = rect->GetSize(), c = rect->GetPosition() + VECTOR2I( s.x / 2, s.y / 2 );
@ -494,17 +531,26 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAP
if( s.x >= s.y ) if( s.x >= s.y )
{ {
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c + d_offset, c + d_offset + VECTOR2I(l, l))); breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_offset,
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c + d_offset, c + d_offset - VECTOR2I(-l, l))); c + d_offset + VECTOR2I( l, l ) ) );
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c - d_offset, c - d_offset + VECTOR2I(-l, l))); breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_offset,
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c - d_offset, c - d_offset - VECTOR2I(l, l))); c + d_offset - VECTOR2I( -l, l ) ) );
} else { breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_offset,
c - d_offset + VECTOR2I( -l, l ) ) );
breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_offset,
c - d_offset - VECTOR2I( l, l ) ) );
}
else
{
// fixme: this could be done more efficiently // fixme: this could be done more efficiently
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c + d_offset, c + d_offset + VECTOR2I(l, l))); breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_offset,
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c - d_offset, c - d_offset - VECTOR2I(-l, l))); c + d_offset + VECTOR2I( l, l ) ) );
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c + d_offset, c + d_offset + VECTOR2I(-l, l))); breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_offset,
breakouts.push_back ( SHAPE_LINE_CHAIN ( c, c - d_offset, c - d_offset - VECTOR2I(l, l))); c - d_offset - VECTOR2I( -l, l ) ) );
breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_offset,
c + d_offset + VECTOR2I( -l, l ) ) );
breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_offset,
c - d_offset - VECTOR2I( l, l ) ) );
} }
} }
@ -512,8 +558,8 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, const SHAP
} }
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth,
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, const PNS_ITEM *aItem, bool aPermitDiagonal ) const const PNS_ITEM* aItem, bool aPermitDiagonal ) const
{ {
switch( aItem->GetKind() ) switch( aItem->GetKind() )
{ {
@ -526,25 +572,32 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, const P
case PNS_ITEM::SOLID: case PNS_ITEM::SOLID:
{ {
const SHAPE* shape = aItem->GetShape(); const SHAPE* shape = aItem->GetShape();
switch( shape->Type() ) switch( shape->Type() )
{ {
case SH_RECT: case SH_RECT:
return rectBreakouts( aWidth, shape, aPermitDiagonal ); return rectBreakouts( aWidth, shape, aPermitDiagonal );
case SH_CIRCLE: case SH_CIRCLE:
return circleBreakouts( aWidth, shape, aPermitDiagonal ); return circleBreakouts( aWidth, shape, aPermitDiagonal );
default: default:
break; break;
} }
} }
default: default:
break; break;
} }
return BreakoutList(); return BreakoutList();
} }
PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const
{ {
PNS_NODE::OptJoint jt = m_world->FindJoint( aP, aLayer, aNet ); PNS_NODE::OptJoint jt = m_world->FindJoint( aP, aLayer, aNet );
if( !jt ) if( !jt )
return NULL; return NULL;
@ -553,16 +606,19 @@ PNS_ITEM *PNS_OPTIMIZER::findPadOrVia ( int aLayer, int aNet, const VECTOR2I& aP
if( item->GetKind() == PNS_ITEM::VIA || item->GetKind() == PNS_ITEM::SOLID ) if( item->GetKind() == PNS_ITEM::VIA || item->GetKind() == PNS_ITEM::SOLID )
return item; return item;
} }
return NULL; return NULL;
} }
int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex ) int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex )
{ {
int min_cost = INT_MAX; // PNS_COST_ESTIMATOR::CornerCost( line ); int min_cost = INT_MAX; // PNS_COST_ESTIMATOR::CornerCost( line );
int min_len = INT_MAX; int min_len = INT_MAX;
DIRECTION_45 dir; DIRECTION_45 dir;
const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE | DIRECTION_45::ANG_RIGHT | DIRECTION_45::ANG_HALF_FULL | DIRECTION_45::ANG_UNDEFINED; const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE | DIRECTION_45::ANG_RIGHT |
DIRECTION_45::ANG_HALF_FULL | DIRECTION_45::ANG_UNDEFINED;
typedef pair<int, SHAPE_LINE_CHAIN> RtVariant; typedef pair<int, SHAPE_LINE_CHAIN> RtVariant;
vector<RtVariant> variants; vector<RtVariant> variants;
@ -577,15 +633,15 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
for( int p = 1; p <= p_end; p++ ) for( int p = 1; p <= p_end; p++ )
{ {
BOOST_FOREACH(SHAPE_LINE_CHAIN& l, breakouts) BOOST_FOREACH( SHAPE_LINE_CHAIN & l, breakouts ) {
{
// PNSDisplayDebugLine (l, 0); // PNSDisplayDebugLine (l, 0);
for( int diag = 0; diag < 2; diag++ ) for( int diag = 0; diag < 2; diag++ )
{ {
SHAPE_LINE_CHAIN v; SHAPE_LINE_CHAIN v;
SHAPE_LINE_CHAIN connect = dir.BuildInitialTrace( l.CPoint(-1), line.CPoint(p), diag == 0); SHAPE_LINE_CHAIN connect = dir.BuildInitialTrace( l.CPoint( -1 ),
line.CPoint( p ), diag == 0 );
DIRECTION_45 dir_bkout( l.CSegment( -1 ) ); DIRECTION_45 dir_bkout( l.CSegment( -1 ) );
// DIRECTION_45 dir_head ( line.CSegment(p + 1)); // DIRECTION_45 dir_head ( line.CSegment(p + 1));
@ -619,7 +675,6 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
vp.second.Simplify(); vp.second.Simplify();
variants.push_back( vp ); variants.push_back( vp );
} }
} }
} }
} }
@ -636,12 +691,10 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
if( !checkColliding( &tmp ) ) if( !checkColliding( &tmp ) )
{ {
/* if(aEnd) /* if(aEnd)
PNSDisplayDebugLine (l_best, 6); * PNSDisplayDebugLine (l_best, 6);
else * else
PNSDisplayDebugLine (l_best, 5);*/ * PNSDisplayDebugLine (l_best, 5);*/
if( cost < min_cost || ( cost == min_cost && len < min_len ) ) if( cost < min_cost || ( cost == min_cost && len < min_len ) )
{ {
@ -652,9 +705,9 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
// if(cost == min_cost) // if(cost == min_cost)
if( cost == min_cost ) if( cost == min_cost )
min_len = std::min( len, min_len ); min_len = std::min( len, min_len );
min_cost = std::min( cost, min_cost ); min_cost = std::min( cost, min_cost );
} }
} }
} }
@ -669,9 +722,11 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
aLine->SetShape( l_best ); aLine->SetShape( l_best );
return p_best; return p_best;
} }
return -1; return -1;
} }
bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine ) bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine )
{ {
SHAPE_LINE_CHAIN& line = aLine->GetLine(); SHAPE_LINE_CHAIN& line = aLine->GetLine();
@ -688,17 +743,22 @@ bool PNS_OPTIMIZER::runSmartPads(PNS_LINE *aLine)
if( startPad ) if( startPad )
vtx = smartPadsSingle( aLine, startPad, false, 3 ); vtx = smartPadsSingle( aLine, startPad, false, 3 );
if( endPad ) if( endPad )
smartPadsSingle(aLine, endPad, true, vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx); smartPadsSingle( aLine, endPad, true,
vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx );
aLine->GetLine().Simplify(); aLine->GetLine().Simplify();
return true; return true;
} }
bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld ) bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld )
{ {
PNS_OPTIMIZER opt( aWorld ? aWorld : aLine->GetWorld() ); PNS_OPTIMIZER opt( aWorld ? aWorld : aLine->GetWorld() );
opt.SetEffortLevel( aEffortLevel ); opt.SetEffortLevel( aEffortLevel );
opt.SetCollisionMask( -1 ); opt.SetCollisionMask( -1 );
return opt.Optimize( aLine ); return opt.Optimize( aLine );
} }

View File

@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_OPTIMIZER_H #ifndef __PNS_OPTIMIZER_H
#define __PNS_OPTIMIZER_H #define __PNS_OPTIMIZER_H
@ -30,7 +31,6 @@ class PNS_NODE;
class PNS_LINE; class PNS_LINE;
class PNS_ROUTER; class PNS_ROUTER;
/** /**
* Class PNS_COST_ESTIMATOR * Class PNS_COST_ESTIMATOR
* *
@ -60,7 +60,8 @@ class PNS_COST_ESTIMATOR
void Remove( PNS_LINE& aLine ); void Remove( PNS_LINE& aLine );
void Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine ); void Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine );
bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance, double aCornerTollerace ) const; bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance,
double aCornerTollerace ) const;
double GetLengthCost() const { return m_lengthCost; } double GetLengthCost() const { return m_lengthCost; }
double GetCornerCost() const { return m_cornerCost; } double GetCornerCost() const { return m_cornerCost; }
@ -85,11 +86,11 @@ class PNS_COST_ESTIMATOR
class PNS_OPTIMIZER class PNS_OPTIMIZER
{ {
public: public:
enum OptimizationEffort
enum OptimizationEffort { {
MERGE_SEGMENTS = 0x1, MERGE_SEGMENTS = 0x01,
SMART_PADS = 0x2, SMART_PADS = 0x02,
MERGE_OBTUSE = 0x4 MERGE_OBTUSE = 0x04
}; };
PNS_OPTIMIZER( PNS_NODE* aWorld ); PNS_OPTIMIZER( PNS_NODE* aWorld );
@ -98,7 +99,8 @@ class PNS_OPTIMIZER
///> a quick shortcut to optmize a line without creating and setting up an optimizer ///> a quick shortcut to optmize a line without creating and setting up an optimizer
static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld = NULL ); static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld = NULL );
bool Optimize ( PNS_LINE *aLine, PNS_LINE *aResult = NULL, int aStartVertex = 0, int aEndVertex = -1); bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL,
int aStartVertex = 0, int aEndVertex = -1 );
void SetWorld( PNS_NODE* aNode ) { m_world = aNode; } void SetWorld( PNS_NODE* aNode ) { m_world = aNode; }
void CacheStaticItem( PNS_ITEM* aItem ); void CacheStaticItem( PNS_ITEM* aItem );
@ -116,7 +118,6 @@ class PNS_OPTIMIZER
} }
private: private:
static const int MaxCachedItems = 256; static const int MaxCachedItems = 256;
typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList; typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList;
@ -145,7 +146,8 @@ class PNS_OPTIMIZER
BreakoutList circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; BreakoutList circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; BreakoutList rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const; BreakoutList ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList computeBreakouts( int aWidth, const PNS_ITEM *aItem, bool aPermitDiagonal ) const; BreakoutList computeBreakouts( int aWidth, const PNS_ITEM* aItem,
bool aPermitDiagonal ) const;
int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex ); int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex );
@ -162,3 +164,4 @@ class PNS_OPTIMIZER
}; };
#endif #endif

View File

@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#include <cstdio> #include <cstdio>
#include <vector> #include <vector>
@ -52,7 +53,8 @@
using namespace std; using namespace std;
// an ugly singleton for drawing debug items within the router context. To be fixed sometime in the future. // an ugly singleton for drawing debug items within the router context.
// To be fixed sometime in the future.
static PNS_ROUTER* theRouter; static PNS_ROUTER* theRouter;
class PCBNEW_CLEARANCE_FUNC : public PNS_CLEARANCE_FUNC class PCBNEW_CLEARANCE_FUNC : public PNS_CLEARANCE_FUNC
@ -69,7 +71,8 @@ class PCBNEW_CLEARANCE_FUNC : public PNS_CLEARANCE_FUNC
NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName ); NETCLASS* nc = aBoard->m_NetClasses.Find( netClassName );
int clearance = nc->GetClearance(); int clearance = nc->GetClearance();
m_clearanceCache[i] = clearance; m_clearanceCache[i] = clearance;
TRACE(1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % clearance); TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() %
clearance );
} }
m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
@ -81,11 +84,11 @@ class PCBNEW_CLEARANCE_FUNC : public PNS_CLEARANCE_FUNC
int cl_a = (net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance); int cl_a = (net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance);
int net_b = b->GetNet(); int net_b = b->GetNet();
int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance); int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance);
return std::max( cl_a, cl_b ); return std::max( cl_a, cl_b );
} }
private: private:
vector<int> m_clearanceCache; vector<int> m_clearanceCache;
int m_defaultClearance; int m_defaultClearance;
}; };
@ -99,6 +102,7 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
case PAD_STANDARD: case PAD_STANDARD:
layers = PNS_LAYERSET( 0, 15 ); layers = PNS_LAYERSET( 0, 15 );
break; break;
case PAD_SMD: case PAD_SMD:
case PAD_CONN: case PAD_CONN:
{ {
@ -111,8 +115,11 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
layers = PNS_LAYERSET( i ); layers = PNS_LAYERSET( i );
break; break;
} }
break; break;
} }
default: default:
TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() ); TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() );
return NULL; return NULL;
@ -130,7 +137,6 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
solid->SetCenter( c ); solid->SetCenter( c );
double orient = aPad->GetOrientation() / 10.0; double orient = aPad->GetOrientation() / 10.0;
if( orient == 90.0 || orient == 270.0 ) if( orient == 90.0 || orient == 270.0 )
@ -147,6 +153,7 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
case PAD_CIRCLE: case PAD_CIRCLE:
solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
break; break;
case PAD_OVAL: case PAD_OVAL:
if( sz.x == sz.y ) if( sz.x == sz.y )
solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
@ -164,15 +171,15 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
return NULL; return NULL;
} }
solid->SetParent( aPad ); solid->SetParent( aPad );
return solid; return solid;
} }
PNS_ITEM* PNS_ROUTER::syncTrack( TRACK* aTrack ) PNS_ITEM* PNS_ROUTER::syncTrack( TRACK* aTrack )
{ {
PNS_SEGMENT* s =
PNS_SEGMENT *s = new PNS_SEGMENT( SEG (aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNet() ); new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNet() );
s->SetWidth( aTrack->GetWidth() ); s->SetWidth( aTrack->GetWidth() );
s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) ); s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) );
@ -193,12 +200,14 @@ PNS_ITEM *PNS_ROUTER::syncVia( SEGVIA *aVia )
return v; return v;
} }
void PNS_ROUTER::SetBoard( BOARD* aBoard ) void PNS_ROUTER::SetBoard( BOARD* aBoard )
{ {
m_board = aBoard; m_board = aBoard;
TRACE( 1, "m_board = %p\n", m_board ); TRACE( 1, "m_board = %p\n", m_board );
} }
int PNS_ROUTER::NextCopperLayer( bool aUp ) int PNS_ROUTER::NextCopperLayer( bool aUp )
{ {
LAYER_MSK mask = m_board->GetEnabledLayers() & m_board->GetVisibleLayers(); LAYER_MSK mask = m_board->GetEnabledLayers() & m_board->GetVisibleLayers();
@ -206,6 +215,7 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
do { do {
l += ( aUp ? 1 : -1 ); l += ( aUp ? 1 : -1 );
if( l > LAST_COPPER_LAYER ) if( l > LAST_COPPER_LAYER )
l = FIRST_COPPER_LAYER; l = FIRST_COPPER_LAYER;
@ -214,12 +224,12 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
if( mask & GetLayerMask( l ) ) if( mask & GetLayerMask( l ) )
return l; return l;
} while( l != m_currentLayer ); } while( l != m_currentLayer );
return l; return l;
} }
void PNS_ROUTER::SyncWorld() void PNS_ROUTER::SyncWorld()
{ {
vector<D_PAD*> pads; vector<D_PAD*> pads;
@ -239,9 +249,9 @@ void PNS_ROUTER::SyncWorld()
m_world->SetMaxClearance( 1000000 ); // m_board->GetBiggestClearanceValue()); m_world->SetMaxClearance( 1000000 ); // m_board->GetBiggestClearanceValue());
pads = m_board->GetPads(); pads = m_board->GetPads();
BOOST_FOREACH( D_PAD *pad, pads ) BOOST_FOREACH( D_PAD * pad, pads ) {
{
PNS_ITEM* solid = syncPad( pad ); PNS_ITEM* solid = syncPad( pad );
if( solid ) if( solid )
m_world->Add( solid ); m_world->Add( solid );
} }
@ -250,6 +260,7 @@ void PNS_ROUTER::SyncWorld()
{ {
KICAD_T type = t->Type(); KICAD_T type = t->Type();
PNS_ITEM* item = NULL; PNS_ITEM* item = NULL;
if( type == PCB_TRACE_T ) if( type == PCB_TRACE_T )
item = syncTrack( t ); item = syncTrack( t );
else if( type == PCB_VIA_T ) else if( type == PCB_VIA_T )
@ -262,6 +273,7 @@ void PNS_ROUTER::SyncWorld()
m_placer = new PNS_LINE_PLACER( m_world ); m_placer = new PNS_LINE_PLACER( m_world );
} }
PNS_ROUTER::PNS_ROUTER() PNS_ROUTER::PNS_ROUTER()
{ {
theRouter = this; theRouter = this;
@ -295,26 +307,30 @@ void PNS_ROUTER::SetView(KiGfx::VIEW *aView)
m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) ); m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) );
m_view->Add( m_previewItems ); m_view->Add( m_previewItems );
m_previewItems->ViewSetVisible( true ); m_previewItems->ViewSetVisible( true );
} }
PNS_ROUTER* PNS_ROUTER::GetInstance() PNS_ROUTER* PNS_ROUTER::GetInstance()
{ {
return theRouter; return theRouter;
} }
PNS_ROUTER::~PNS_ROUTER() PNS_ROUTER::~PNS_ROUTER()
{ {
ClearWorld(); ClearWorld();
theRouter = NULL; theRouter = NULL;
} }
void PNS_ROUTER::ClearWorld() void PNS_ROUTER::ClearWorld()
{ {
if( m_world ) if( m_world )
delete m_world; delete m_world;
if( m_clearanceFunc ) if( m_clearanceFunc )
delete m_clearanceFunc; delete m_clearanceFunc;
if( m_placer ) if( m_placer )
delete m_placer; delete m_placer;
@ -323,12 +339,14 @@ void PNS_ROUTER::ClearWorld()
m_placer = NULL; m_placer = NULL;
} }
void PNS_ROUTER::SetCurrentWidth( int w ) void PNS_ROUTER::SetCurrentWidth( int w )
{ {
// fixme: change width while routing // fixme: change width while routing
m_currentWidth = w; m_currentWidth = w;
} }
bool PNS_ROUTER::RoutingInProgress() const bool PNS_ROUTER::RoutingInProgress() const
{ {
return m_state != IDLE; return m_state != IDLE;
@ -360,10 +378,12 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM *item, VECTOR2I aP, bool& aSplit
anchor = static_cast<PNS_SOLID*>(item)->GetCenter(); anchor = static_cast<PNS_SOLID*>(item)->GetCenter();
aSplitsSegment = false; aSplitsSegment = false;
break; break;
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
anchor = static_cast<PNS_VIA*>(item)->GetPos(); anchor = static_cast<PNS_VIA*>(item)->GetPos();
aSplitsSegment = false; aSplitsSegment = false;
break; break;
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
{ {
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>(item); PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>(item);
@ -376,15 +396,19 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM *item, VECTOR2I aP, bool& aSplit
anchor = s.a; anchor = s.a;
else if( (aP - s.b).EuclideanNorm() < w / 2 ) else if( (aP - s.b).EuclideanNorm() < w / 2 )
anchor = s.b; anchor = s.b;
else { else
{
anchor = s.NearestPoint( aP ); anchor = s.NearestPoint( aP );
aSplitsSegment = true; aSplitsSegment = true;
} }
break; break;
} }
default: default:
break; break;
} }
return anchor; return anchor;
} }
@ -412,21 +436,22 @@ void PNS_ROUTER::StartRouting(const VECTOR2I& aP, PNS_ITEM *aStartItem)
m_originalStart = p; m_originalStart = p;
m_currentEnd = p; m_currentEnd = p;
m_placer->SetInitialDirection(m_start_diagonal ? DIRECTION_45(DIRECTION_45::NE) : DIRECTION_45(DIRECTION_45::N)); m_placer->SetInitialDirection( m_start_diagonal ? DIRECTION_45(
DIRECTION_45::NE ) : DIRECTION_45( DIRECTION_45::N ) );
m_placer->StartPlacement( m_originalStart, m_currentNet, m_currentWidth, m_currentLayer ); m_placer->StartPlacement( m_originalStart, m_currentNet, m_currentWidth, m_currentLayer );
m_state = ROUTE_TRACK; m_state = ROUTE_TRACK;
if( splitSeg ) if( splitSeg )
splitAdjacentSegments( m_placer->GetCurrentNode(), aStartItem, p ); splitAdjacentSegments( m_placer->GetCurrentNode(), aStartItem, p );
} }
const VECTOR2I PNS_ROUTER::GetCurrentEnd() const const VECTOR2I PNS_ROUTER::GetCurrentEnd() const
{ {
return m_currentEnd; return m_currentEnd;
} }
void PNS_ROUTER::EraseView() void PNS_ROUTER::EraseView()
{ {
BOOST_FOREACH( BOARD_ITEM* item, m_hiddenItems ) BOOST_FOREACH( BOARD_ITEM* item, m_hiddenItems )
@ -436,15 +461,17 @@ void PNS_ROUTER::EraseView()
if( m_previewItems ) if( m_previewItems )
m_previewItems->FreeItems(); m_previewItems->FreeItems();
m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY ); m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY );
} }
void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, bool aIsHead ) void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, bool aIsHead )
{ {
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems );
m_previewItems->Add( pitem ); m_previewItems->Add( pitem );
if( aIsHead ) if( aIsHead )
pitem->MarkAsHead(); pitem->MarkAsHead();
@ -452,6 +479,7 @@ void PNS_ROUTER::DisplayItem(const PNS_ITEM* aItem, bool aIsHead)
m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY | KiGfx::VIEW_ITEM::APPEARANCE ); m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY | KiGfx::VIEW_ITEM::APPEARANCE );
} }
void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth )
{ {
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems );
@ -462,9 +490,9 @@ void PNS_ROUTER::DisplayDebugLine ( const SHAPE_LINE_CHAIN &aLine, int aType, in
m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY | KiGfx::VIEW_ITEM::APPEARANCE ); m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY | KiGfx::VIEW_ITEM::APPEARANCE );
} }
void PNS_ROUTER::DisplayDebugBox( const BOX2I& aBox, int aType, int aWidth ) void PNS_ROUTER::DisplayDebugBox( const BOX2I& aBox, int aType, int aWidth )
{ {
} }
@ -476,9 +504,9 @@ void PNS_ROUTER::Move(const VECTOR2I& aP, PNS_ITEM *endItem)
if( m_state == IDLE ) if( m_state == IDLE )
return; return;
// TODO is something missing here?
if( m_state == START_ROUTING ) if( m_state == START_ROUTING )
{ {
} }
EraseView(); EraseView();
@ -495,8 +523,7 @@ void PNS_ROUTER::Move(const VECTOR2I& aP, PNS_ITEM *endItem)
m_placer->GetCurrentNode()->GetUpdatedItems( removed, added ); m_placer->GetCurrentNode()->GetUpdatedItems( removed, added );
BOOST_FOREACH(PNS_ITEM *item, added) BOOST_FOREACH( PNS_ITEM* item, added ) {
{
DisplayItem( item ); DisplayItem( item );
} }
@ -515,6 +542,7 @@ void PNS_ROUTER::Move(const VECTOR2I& aP, PNS_ITEM *endItem)
} }
} }
void PNS_ROUTER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ) void PNS_ROUTER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP )
{ {
if( aSeg && aSeg->OfKind( PNS_ITEM::SEGMENT ) ) if( aSeg && aSeg->OfKind( PNS_ITEM::SEGMENT ) )
@ -533,13 +561,13 @@ void PNS_ROUTER::splitAdjacentSegments(PNS_NODE *aNode, PNS_ITEM *aSeg, const VE
s_new[0]->SetEnds( s_old->GetSeg().a, aP ); s_new[0]->SetEnds( s_old->GetSeg().a, aP );
s_new[1]->SetEnds( aP, s_old->GetSeg().b ); s_new[1]->SetEnds( aP, s_old->GetSeg().b );
aNode->Remove( s_old ); aNode->Remove( s_old );
aNode->Add( s_new[0] ); aNode->Add( s_new[0] );
aNode->Add( s_new[1] ); aNode->Add( s_new[1] );
} }
} }
void PNS_ROUTER::commitRouting( PNS_NODE* aNode ) void PNS_ROUTER::commitRouting( PNS_NODE* aNode )
{ {
PNS_NODE::ItemVector removed, added; PNS_NODE::ItemVector removed, added;
@ -560,6 +588,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
BOOST_FOREACH( PNS_ITEM* item, added ) BOOST_FOREACH( PNS_ITEM* item, added )
{ {
BOARD_ITEM* newBI = NULL; BOARD_ITEM* newBI = NULL;
switch( item->GetKind() ) switch( item->GetKind() )
{ {
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
@ -605,6 +634,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
m_world->Commit( aNode ); m_world->Commit( aNode );
} }
PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const
{ {
PNS_VIA* theVia = NULL; PNS_VIA* theVia = NULL;
@ -615,22 +645,23 @@ PNS_VIA *PNS_ROUTER::checkLoneVia ( PNS_JOINT* aJoint ) const
if( item->GetKind() == PNS_ITEM::VIA ) if( item->GetKind() == PNS_ITEM::VIA )
theVia = static_cast<PNS_VIA*>( item ); theVia = static_cast<PNS_VIA*>( item );
l.Merge( item->GetLayers() ); l.Merge( item->GetLayers() );
} }
if( l.Start() == l.End() ) if( l.Start() == l.End() )
return theVia; return theVia;
return NULL; return NULL;
} }
PNS_NODE* PNS_ROUTER::removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg ) PNS_NODE* PNS_ROUTER::removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg )
{ {
PNS_LINE* ourLine = aNode->AssembleLine( aLatestSeg ); PNS_LINE* ourLine = aNode->AssembleLine( aLatestSeg );
PNS_NODE* cleaned = aNode->Branch(); PNS_NODE* cleaned = aNode->Branch();
PNS_JOINT a, b; PNS_JOINT a, b;
vector<PNS_LINE *> lines;
vector<PNS_LINE*> lines;
cleaned->FindLineEnds( ourLine, a, b ); cleaned->FindLineEnds( ourLine, a, b );
cleaned->FindLinesBetweenJoints( a, b, lines ); cleaned->FindLinesBetweenJoints( a, b, lines );
@ -647,7 +678,6 @@ PNS_NODE *PNS_ROUTER::removeLoops ( PNS_NODE *aNode, PNS_SEGMENT *aLatestSeg )
} }
bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem ) bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
{ {
bool real_end = false; bool real_end = false;
@ -676,6 +706,7 @@ bool PNS_ROUTER::FixRoute(const VECTOR2I& aP, PNS_ITEM *aEndItem)
splitAdjacentSegments( latest, aEndItem, aP ); splitAdjacentSegments( latest, aEndItem, aP );
PNS_SEGMENT* lastSeg = NULL; PNS_SEGMENT* lastSeg = NULL;
for( int i = 0; i < last; i++ ) for( int i = 0; i < last; i++ )
{ {
const SEG& s = pl.GetCLine().CSegment( i ); const SEG& s = pl.GetCLine().CSegment( i );
@ -700,8 +731,9 @@ bool PNS_ROUTER::FixRoute(const VECTOR2I& aP, PNS_ITEM *aEndItem)
{ {
m_state = IDLE; m_state = IDLE;
// m_world->KillChildren(); // m_world->KillChildren();
} else { }
else
{
m_state = ROUTE_TRACK; m_state = ROUTE_TRACK;
m_placer->SetInitialDirection( d_last ); m_placer->SetInitialDirection( d_last );
m_currentStart = m_placingVia ? p_last : p_pre_last; m_currentStart = m_placingVia ? p_last : p_pre_last;
@ -713,13 +745,12 @@ bool PNS_ROUTER::FixRoute(const VECTOR2I& aP, PNS_ITEM *aEndItem)
m_startsOnVia = m_placingVia; m_startsOnVia = m_placingVia;
m_placingVia = false; m_placingVia = false;
} }
return real_end; return real_end;
} }
void PNS_ROUTER::StopRouting() void PNS_ROUTER::StopRouting()
{ {
if( !RoutingInProgress() ) if( !RoutingInProgress() )
@ -733,18 +764,22 @@ void PNS_ROUTER::StopRouting()
m_world->KillChildren(); m_world->KillChildren();
} }
void PNS_ROUTER::FlipPosture() void PNS_ROUTER::FlipPosture()
{ {
if( m_placer->GetTail().GetCLine().SegmentCount() == 0 ) if( m_placer->GetTail().GetCLine().SegmentCount() == 0 )
{ {
m_start_diagonal = !m_start_diagonal; m_start_diagonal = !m_start_diagonal;
m_placer->SetInitialDirection(m_start_diagonal ? DIRECTION_45(DIRECTION_45::NE) : DIRECTION_45(DIRECTION_45::N)); m_placer->SetInitialDirection( m_start_diagonal ? DIRECTION_45(
} else DIRECTION_45::NE ) : DIRECTION_45( DIRECTION_45::N ) );
}
else
m_placer->FlipPosture(); m_placer->FlipPosture();
Move( m_currentEnd, NULL ); Move( m_currentEnd, NULL );
} }
void PNS_ROUTER::SwitchLayer( int layer ) void PNS_ROUTER::SwitchLayer( int layer )
{ {
switch( m_state ) switch( m_state )
@ -752,17 +787,21 @@ void PNS_ROUTER::SwitchLayer(int layer)
case IDLE: case IDLE:
m_currentLayer = layer; m_currentLayer = layer;
break; break;
case ROUTE_TRACK: case ROUTE_TRACK:
if( m_startsOnVia ) if( m_startsOnVia )
{ {
m_currentLayer = layer; m_currentLayer = layer;
m_placer->StartPlacement(m_currentStart, m_currentNet, m_currentWidth, m_currentLayer); m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth,
m_currentLayer );
} }
default: default:
break; break;
} }
} }
void PNS_ROUTER::ToggleViaPlacement() void PNS_ROUTER::ToggleViaPlacement()
{ {
if( m_state == ROUTE_TRACK ) if( m_state == ROUTE_TRACK )

View File

@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_ROUTER_H #ifndef __PNS_ROUTER_H
#define __PNS_ROUTER_H #define __PNS_ROUTER_H
@ -59,10 +60,11 @@ namespace KiGfx {
* Main router class. * Main router class.
*/ */
class PNS_ROUTER { class PNS_ROUTER
{
private: private:
enum RouterState { enum RouterState
{
IDLE, IDLE,
START_ROUTING, START_ROUTING,
ROUTE_TRACK, ROUTE_TRACK,
@ -70,7 +72,6 @@ private:
}; };
public: public:
PNS_ROUTER(); PNS_ROUTER();
~PNS_ROUTER(); ~PNS_ROUTER();
@ -106,10 +107,12 @@ public:
void EraseView(); void EraseView();
void SwitchLayer( int layer ); void SwitchLayer( int layer );
int GetCurrentLayer() const { return m_currentLayer; } int GetCurrentLayer() const { return m_currentLayer; }
void ToggleViaPlacement(); void ToggleViaPlacement();
void SetCurrentWidth( int w ); void SetCurrentWidth( int w );
void SetCurrentViaDiameter( int d ) { m_currentViaDiameter = d; } void SetCurrentViaDiameter( int d ) { m_currentViaDiameter = d; }
void SetCurrentViaDrill( int d ) { m_currentViaDrill = d; } void SetCurrentViaDrill( int d ) { m_currentViaDrill = d; }
int GetCurrentWidth() const { return m_currentWidth; } int GetCurrentWidth() const { return m_currentWidth; }
@ -127,7 +130,6 @@ public:
return m_placingVia; return m_placingVia;
} }
int NextCopperLayer( bool aUp ); int NextCopperLayer( bool aUp );
// typedef boost::optional<hoverItem> optHoverItem; // typedef boost::optional<hoverItem> optHoverItem;
@ -135,11 +137,7 @@ public:
const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP ); const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP );
const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment ); const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment );
private: private:
void clearViewFlags(); void clearViewFlags();
// optHoverItem queryHoverItemEx(const VECTOR2I& aP); // optHoverItem queryHoverItemEx(const VECTOR2I& aP);
@ -161,7 +159,6 @@ private:
void highlightCurrent( bool enabled ); void highlightCurrent( bool enabled );
int m_currentLayer; int m_currentLayer;
int m_currentNet; int m_currentNet;
int m_currentWidth; int m_currentWidth;
@ -191,7 +188,7 @@ private:
PNS_CLEARANCE_FUNC* m_clearanceFunc; PNS_CLEARANCE_FUNC* m_clearanceFunc;
boost::unordered_set<BOARD_ITEM*> m_hiddenItems; boost::unordered_set<BOARD_ITEM*> m_hiddenItems;
}; };
#endif #endif

View File

@ -22,7 +22,8 @@
#define __PNS_ROUTER_SETTINGS #define __PNS_ROUTER_SETTINGS
///> Routing modes ///> Routing modes
enum PNS_MODE { enum PNS_MODE
{
RM_Ignore = 0, ///> Ignore collisions RM_Ignore = 0, ///> Ignore collisions
RM_Shove, ///> Only shove RM_Shove, ///> Only shove
RM_Walkaround, ///> Only walkaround RM_Walkaround, ///> Only walkaround

View File

@ -32,7 +32,8 @@
class PNS_NODE; class PNS_NODE;
class PNS_SEGMENT : public PNS_ITEM { class PNS_SEGMENT : public PNS_ITEM
{
public: public:
PNS_SEGMENT() : PNS_SEGMENT() :
PNS_ITEM( SEGMENT ) PNS_ITEM( SEGMENT )
@ -61,7 +62,8 @@ public:
PNS_SEGMENT* Clone() const; PNS_SEGMENT* Clone() const;
const SHAPE* GetShape() const { const SHAPE* GetShape() const
{
return static_cast<const SHAPE*>( &m_shape ); return static_cast<const SHAPE*>( &m_shape );
} }
@ -85,14 +87,18 @@ public:
m_width = aWidth; m_width = aWidth;
} }
int GetWidth() const { int GetWidth() const
{
return m_width; return m_width;
} }
const SEG GetSeg() const { const SEG GetSeg() const
{
assert( m_shape.PointCount() >= 1 ); assert( m_shape.PointCount() >= 1 );
if( m_shape.PointCount() == 1 ) if( m_shape.PointCount() == 1 )
return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 0 ) ); return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 0 ) );
return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 1 ) ); return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 1 ) );
} }
@ -111,9 +117,9 @@ public:
const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const; const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const;
private: private:
SHAPE_LINE_CHAIN m_shape; SHAPE_LINE_CHAIN m_shape;
int m_width; int m_width;
}; };
#endif #endif

View File

@ -43,11 +43,14 @@ PNS_SHOVE::PNS_SHOVE( PNS_NODE *aWorld )
m_iterLimit = 100; m_iterLimit = 100;
}; };
PNS_SHOVE::~PNS_SHOVE() PNS_SHOVE::~PNS_SHOVE()
{ {
} }
struct range {
struct range
{
range() range()
{ {
min_v = max_v = -1; min_v = max_v = -1;
@ -56,6 +59,7 @@ struct range {
void add( int x ) void add( int x )
{ {
if( min_v < 0 ) min_v = x; if( min_v < 0 ) min_v = x;
if( max_v < 0 ) max_v = x; if( max_v < 0 ) max_v = x;
if( x < min_v ) if( x < min_v )
@ -78,7 +82,8 @@ struct range {
}; };
// fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm. // fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm.
bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult, bool aInvertWinding ) bool PNS_SHOVE::tryShove( PNS_NODE* aNode, PNS_LINE* aHead, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding )
{ {
const SHAPE_LINE_CHAIN& head = aHead->GetCLine(); const SHAPE_LINE_CHAIN& head = aHead->GetCLine();
bool cw = false; bool cw = false;
@ -105,12 +110,14 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
{ {
// printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str()); // printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str());
} }
/*... special case for vias? */ /*... special case for vias? */
return !aNode->CheckColliding( aResult, aHead ); return !aNode->CheckColliding( aResult, aHead );
} }
int ns = head.SegmentCount(); int ns = head.SegmentCount();
if( aHead->EndsWithVia() ) if( aHead->EndsWithVia() )
ns++; ns++;
@ -119,7 +126,6 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
const PNS_SEGMENT hs( *aHead, head.CSegment( i ) ); const PNS_SEGMENT hs( *aHead, head.CSegment( i ) );
if( aNode->CheckColliding( &hs, aObstacle ) ) if( aNode->CheckColliding( &hs, aObstacle ) )
{ {
VECTOR2I v1 = hs.GetSeg().b - hs.GetSeg().a; VECTOR2I v1 = hs.GetSeg().b - hs.GetSeg().a;
@ -158,7 +164,8 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
{ {
const PNS_SEGMENT hs( *aHead, head.CSegment( i ) ); const PNS_SEGMENT hs( *aHead, head.CSegment( i ) );
hull = hs.Hull( clearance, 0 ); hull = hs.Hull( clearance, 0 );
} else }
else
hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 ); hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 );
SHAPE_LINE_CHAIN path_pre, path_walk, path_post, tmp; SHAPE_LINE_CHAIN path_pre, path_walk, path_post, tmp;
@ -168,12 +175,13 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
shoved.NewWalkaround( hull, path_pre, path_walk, path_post, cw ); shoved.NewWalkaround( hull, path_pre, path_walk, path_post, cw );
/*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 ) /*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 )
{ * {
TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str()); * TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str());
TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str()); * TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str());
}*/ * }*/
tmp = shoved.GetCLine(); tmp = shoved.GetCLine();
if( path_walk.SegmentCount() ) if( path_walk.SegmentCount() )
r.add( i ); r.add( i );
@ -188,7 +196,6 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
{ {
// TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str()); // TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str());
} }
} }
TRACE( 2, "CW %d affectedRange %d-%d [total %d]", (cw ? 1 : 0) % r.start() % r.end() % ns ); TRACE( 2, "CW %d affectedRange %d-%d [total %d]", (cw ? 1 : 0) % r.start() % r.end() % ns );
@ -196,7 +203,9 @@ bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle,
return !aNode->CheckColliding( aResult, aHead ); return !aNode->CheckColliding( aResult, aHead );
} }
PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult )
PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent,
PNS_LINE* aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult )
{ {
bool rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, false ); bool rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, false );
@ -214,7 +223,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCu
const SHAPE_LINE_CHAIN& sh_shoved = aResult->GetCLine(); const SHAPE_LINE_CHAIN& sh_shoved = aResult->GetCLine();
const SHAPE_LINE_CHAIN& sh_orig = aObstacle->GetCLine(); const SHAPE_LINE_CHAIN& sh_orig = aObstacle->GetCLine();
if(sh_shoved.SegmentCount() > 1 && sh_shoved.CPoint(0) == sh_orig.CPoint(0) && sh_shoved.CPoint(-1) == sh_orig.CPoint(-1) ) if( sh_shoved.SegmentCount() > 1 && sh_shoved.CPoint( 0 ) == sh_orig.CPoint( 0 )
&& sh_shoved.CPoint( -1 ) == sh_orig.CPoint( -1 ) )
return SH_OK; return SH_OK;
else if( !sh_shoved.SegmentCount() ) else if( !sh_shoved.SegmentCount() )
return SH_NULL; return SH_NULL;
@ -222,6 +232,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCu
return SH_INCOMPLETE; return SH_INCOMPLETE;
} }
bool PNS_SHOVE::reduceSpringback( PNS_LINE* aHead ) bool PNS_SHOVE::reduceSpringback( PNS_LINE* aHead )
{ {
bool rv = false; bool rv = false;
@ -236,13 +247,15 @@ bool PNS_SHOVE::reduceSpringback( PNS_LINE *aHead )
rv = true; rv = true;
delete st_stack.node; delete st_stack.node;
m_nodeStack.pop_back(); m_nodeStack.pop_back();
} else }
else
break; break;
} }
return rv; return rv;
} }
bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost ) bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost )
{ {
BOX2I headBB = aHead->GetCLine().BBox(); BOX2I headBB = aHead->GetCLine().BBox();
@ -255,6 +268,7 @@ bool PNS_SHOVE::pushSpringback( PNS_NODE *aNode, PNS_LINE *aHead, const PNS_COST
return true; return true;
} }
const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const
{ {
if( m_nodeStack.empty() ) if( m_nodeStack.empty() )
@ -263,6 +277,7 @@ const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const
return m_nodeStack.back().cost; return m_nodeStack.back().cost;
} }
PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead )
{ {
stack <PNS_LINE*> lineStack; stack <PNS_LINE*> lineStack;
@ -296,20 +311,20 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
PNS_NODE::OptObstacle nearest; PNS_NODE::OptObstacle nearest;
optimizer.CacheStaticItem( head ); optimizer.CacheStaticItem( head );
if( headVia ) if( headVia )
optimizer.CacheStaticItem( headVia ); optimizer.CacheStaticItem( headVia );
TRACE(1, "ShoveStart [root: %d jts, node: %d jts]", m_root->JointCount() % node->JointCount()); TRACE( 1, "ShoveStart [root: %d jts, node: %d jts]", m_root->JointCount() %
node->JointCount() );
// PNS_ITEM *lastWalkSolid = NULL; // PNS_ITEM *lastWalkSolid = NULL;
prof_counter totalRealTime; prof_counter totalRealTime;
wxLongLong t_start = wxGetLocalTimeMillis(); wxLongLong t_start = wxGetLocalTimeMillis();
while( !lineStack.empty() ) while( !lineStack.empty() )
{ {
wxLongLong t_cur = wxGetLocalTimeMillis(); wxLongLong t_cur = wxGetLocalTimeMillis();
if( (t_cur - t_start).ToLong() > ShoveTimeLimit ) if( (t_cur - t_start).ToLong() > ShoveTimeLimit )
@ -344,7 +359,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
original->GetAffectedRange( r_start, r_end ); original->GetAffectedRange( r_start, r_end );
TRACE(1, "Iter %d optimize-line [range %d-%d, total %d]", iter % r_start % r_end % original->GetCLine().PointCount() ); TRACE( 1, "Iter %d optimize-line [range %d-%d, total %d]",
iter % r_start % r_end % original->GetCLine().PointCount() );
// lastWalkSolid = NULL; // lastWalkSolid = NULL;
prof_start( &totalRealTime, false ); prof_start( &totalRealTime, false );
@ -357,14 +373,16 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
if( original->BelongsTo( node ) ) if( original->BelongsTo( node ) )
delete original; delete original;
} }
prof_end( &totalRealTime ); prof_end( &totalRealTime );
TRACE( 2, "t-optimizeObstacle %lld us", (totalRealTime.value ) ); TRACE( 2, "t-optimizeObstacle %lld us", (totalRealTime.value ) );
} }
lineStack.pop();
} else {
lineStack.pop();
}
else
{
switch( nearest->item->GetKind() ) switch( nearest->item->GetKind() )
{ {
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
@ -376,7 +394,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
PNS_LINE* shovedLine = collidingLine->CloneProperties(); PNS_LINE* shovedLine = collidingLine->CloneProperties();
prof_start( &totalRealTime, false ); prof_start( &totalRealTime, false );
ShoveStatus st = shoveSingleLine(node, currentLine, collidingLine, *pseg, shovedLine); ShoveStatus st = shoveSingleLine( node, currentLine, collidingLine,
*pseg, shovedLine );
prof_end( &totalRealTime ); prof_end( &totalRealTime );
TRACE( 2, "t-shoveSingle %lld us", (totalRealTime.value ) ); TRACE( 2, "t-shoveSingle %lld us", (totalRealTime.value ) );
@ -390,7 +409,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
optimizer.CacheRemove( collidingLine ); optimizer.CacheRemove( collidingLine );
lineStack.push( shovedLine ); lineStack.push( shovedLine );
} else }
else
fail = true; fail = true;
// lastWalkSolid = NULL; // lastWalkSolid = NULL;
@ -410,10 +430,10 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
} }
/* if(lastWalkSolid == nearest->item) /* if(lastWalkSolid == nearest->item)
{ * {
fail = true; * fail = true;
break; * break;
}*/ * }*/
PNS_WALKAROUND walkaround( node ); PNS_WALKAROUND walkaround( node );
PNS_LINE* walkaroundLine = currentLine->CloneProperties(); PNS_LINE* walkaroundLine = currentLine->CloneProperties();
@ -439,9 +459,11 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
// lastWalkSolid = nearest->item; // lastWalkSolid = nearest->item;
break; break;
} }
default: default:
break; break;
} // switch } // switch
if( fail ) if( fail )
break; break;
} }
@ -457,11 +479,14 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
} }
TRACE( 1, "Shove status : %s after %d iterations", (fail ? "FAILED" : "OK") % iter ); TRACE( 1, "Shove status : %s after %d iterations", (fail ? "FAILED" : "OK") % iter );
if( !fail ) if( !fail )
{ {
pushSpringback( node, aCurrentHead, PNS_COST_ESTIMATOR() ); pushSpringback( node, aCurrentHead, PNS_COST_ESTIMATOR() );
return SH_OK; return SH_OK;
} else { }
else
{
delete node; delete node;
return SH_INCOMPLETE; return SH_INCOMPLETE;
} }

View File

@ -30,13 +30,14 @@ class PNS_LINE;
class PNS_NODE; class PNS_NODE;
class PNS_ROUTER; class PNS_ROUTER;
class PNS_SHOVE { class PNS_SHOVE
{
public: public:
PNS_SHOVE( PNS_NODE* aWorld ); PNS_SHOVE( PNS_NODE* aWorld );
~PNS_SHOVE(); ~PNS_SHOVE();
enum ShoveStatus { enum ShoveStatus
{
SH_OK = 0, SH_OK = 0,
SH_NULL, SH_NULL,
SH_INCOMPLETE SH_INCOMPLETE
@ -55,17 +56,19 @@ class PNS_SHOVE {
void KillChildNodes(); void KillChildNodes();
private: private:
static const int ShoveTimeLimit = 3000; static const int ShoveTimeLimit = 3000;
bool tryShove(PNS_NODE *aWorld, PNS_LINE *aTrack, PNS_LINE * aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult, bool aInvertWinding ); bool tryShove( PNS_NODE* aWorld, PNS_LINE* aTrack, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding );
ShoveStatus shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult ); ShoveStatus shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult );
bool reduceSpringback( PNS_LINE* aHead ); bool reduceSpringback( PNS_LINE* aHead );
bool pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost ); bool pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost );
struct SpringbackTag { struct SpringbackTag
{
int64_t length; int64_t length;
int segments; int segments;
VECTOR2I p; VECTOR2I p;
@ -80,3 +83,4 @@ class PNS_SHOVE {
}; };
#endif #endif

View File

@ -35,21 +35,18 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness)
case SH_RECT: case SH_RECT:
{ {
SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape ); SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape );
return OctagonalHull( rect->GetPosition(), return OctagonalHull( rect->GetPosition(), rect->GetSize(),
rect->GetSize(), aClearance + 1, 0.2 * aClearance );
aClearance + 1,
0.2 * aClearance );
} }
case SH_CIRCLE: case SH_CIRCLE:
{ {
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape ); SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
int r = circle->GetRadius(); int r = circle->GetRadius();
return OctagonalHull( circle->GetCenter() - VECTOR2I(r, r), return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
VECTOR2I(2 * r, 2 * r), aClearance + 1, 0.52 * (r + aClearance) );
aClearance + 1,
0.52 * (r + aClearance) );
} }
default: default:
break; break;
} }
@ -57,8 +54,10 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness)
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
} }
PNS_ITEM* PNS_SOLID::Clone() const PNS_ITEM* PNS_SOLID::Clone() const
{ {
// solids are never cloned as the shove algorithm never moves them // solids are never cloned as the shove algorithm never moves them
assert( false ); assert( false );
} }

View File

@ -29,7 +29,8 @@
#include "pns_item.h" #include "pns_item.h"
class PNS_SOLID : public PNS_ITEM { class PNS_SOLID : public PNS_ITEM
{
public: public:
PNS_SOLID() : PNS_ITEM( SOLID ) PNS_SOLID() : PNS_ITEM( SOLID )
{ {
@ -47,6 +48,7 @@ public:
{ {
if( m_shape ) if( m_shape )
delete m_shape; delete m_shape;
m_shape = shape; m_shape = shape;
} }
@ -61,7 +63,6 @@ public:
} }
private: private:
VECTOR2I m_center; VECTOR2I m_center;
SHAPE* m_shape; SHAPE* m_shape;
}; };

View File

@ -22,7 +22,10 @@
#include "pns_line.h" #include "pns_line.h"
#include "pns_router.h" #include "pns_router.h"
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, int aChamfer) const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0,
const VECTOR2I& aSize,
int aClearance,
int aChamfer )
{ {
SHAPE_LINE_CHAIN s; SHAPE_LINE_CHAIN s;

View File

@ -24,10 +24,10 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
/** Various utility functions */ /** Various utility functions */
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, int aChamfer); const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
int aClearance, int aChamfer );
#endif // __PNS_UTILS_H #endif // __PNS_UTILS_H

View File

@ -26,7 +26,6 @@
static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force ) static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force )
{ {
int mindist = r1 + r2; int mindist = r1 + r2;
VECTOR2I delta = p2 - p1; VECTOR2I delta = p2 - p1;
int dist = delta.EuclideanNorm(); int dist = delta.EuclideanNorm();
@ -40,11 +39,14 @@ static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& f
static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force ) static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force )
{ {
VECTOR2I vts[] = { VECTOR2I(rp0.x, rp0.y), VECTOR2I vts[] =
{
VECTOR2I( rp0.x, rp0.y ),
VECTOR2I( rp0.x, rp0.y + rsize.y ), VECTOR2I( rp0.x, rp0.y + rsize.y ),
VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ), VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ),
VECTOR2I( rp0.x + rsize.x, rp0.y ), VECTOR2I( rp0.x + rsize.x, rp0.y ),
VECTOR2I(rp0.x, rp0.y) }; VECTOR2I( rp0.x, rp0.y )
};
int dist = INT_MAX; int dist = INT_MAX;
VECTOR2I nearest; VECTOR2I nearest;
@ -56,6 +58,7 @@ static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECT
VECTOR2I pn = s.NearestPoint( cc ); VECTOR2I pn = s.NearestPoint( cc );
int d = (pn - cc).EuclideanNorm(); int d = (pn - cc).EuclideanNorm();
if( d < dist ) if( d < dist )
{ {
nearest = pn; nearest = pn;
@ -89,20 +92,26 @@ static bool ShPushoutForce ( const SHAPE *shape, VECTOR2I p, int r, VECTOR2I& fo
const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>(shape); const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>(shape);
return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force ); return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force );
} }
case SH_RECT: case SH_RECT:
{ {
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(shape); const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(shape);
return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force ); return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force );
} }
default: default:
return false; return false;
} }
return false; return false;
} }
bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR2I& aForce, bool aSolidsOnly, int aMaxIterations) bool PNS_VIA::PushoutForce( PNS_NODE* aNode,
const VECTOR2I& aDirection,
VECTOR2I& aForce,
bool aSolidsOnly,
int aMaxIterations )
{ {
int iter = 0; int iter = 0;
PNS_VIA mv( *this ); PNS_VIA mv( *this );
@ -110,7 +119,8 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
while( iter < aMaxIterations ) while( iter < aMaxIterations )
{ {
PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY); PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv,
aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
if( !obs ) if( !obs )
break; break;
@ -124,7 +134,8 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
mv.SetPos( mv.GetPos() + l ); mv.SetPos( mv.GetPos() + l );
} }
if( ShPushoutForce(obs->item->GetShape(), mv.GetPos(), mv.GetDiameter() / 2, force, clearance) ) if( ShPushoutForce( obs->item->GetShape(), mv.GetPos(), mv.GetDiameter() / 2, force,
clearance ) )
{ {
totalForce += force; totalForce += force;
mv.SetPos( mv.GetPos() + force ); mv.SetPos( mv.GetPos() + force );
@ -141,8 +152,10 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
return true; return true;
} }
const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const
{ {
return OctagonalHull( m_pos - VECTOR2I(m_diameter/2, m_diameter/2), VECTOR2I(m_diameter, m_diameter), aClearance + 1, (2*aClearance + m_diameter) * 0.26); return OctagonalHull( m_pos -
VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter,
m_diameter ), aClearance + 1, (2 * aClearance + m_diameter) * 0.26 );
} }

View File

@ -35,7 +35,8 @@ class PNS_VIA : public PNS_ITEM
PNS_ITEM( VIA ) {}; PNS_ITEM( VIA ) {};
PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) : PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) :
PNS_ITEM (VIA) { PNS_ITEM( VIA )
{
SetNet( aNet ); SetNet( aNet );
SetLayers( aLayers ); SetLayers( aLayers );
m_pos = aPos; m_pos = aPos;
@ -85,7 +86,11 @@ class PNS_VIA : public PNS_ITEM
m_drill = aDrill; m_drill = aDrill;
} }
bool PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR2I& aForce, bool aSolidsOnly = true, int aMaxIterations = 10); bool PushoutForce( PNS_NODE* aNode,
const VECTOR2I& aDirection,
VECTOR2I& aForce,
bool aSolidsOnly = true,
int aMaxIterations = 10 );
const SHAPE* GetShape() const const SHAPE* GetShape() const
{ {

View File

@ -42,13 +42,16 @@ void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath ) PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
{ {
return m_world->NearestObstacle ( &aPath, m_solids_only ? (PNS_ITEM::SOLID | PNS_ITEM::VIA) : PNS_ITEM::ANY ); return m_world->NearestObstacle( &aPath,
m_solids_only ? (PNS_ITEM::SOLID | PNS_ITEM::VIA) : PNS_ITEM::ANY );
} }
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, bool aWindingDirection) PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
bool aWindingDirection )
{ {
optional<PNS_OBSTACLE>& current_obs = aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1]; optional<PNS_OBSTACLE>& current_obs =
aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1];
bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1]; bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1];
if( !current_obs ) if( !current_obs )
@ -64,22 +67,25 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
if( m_recursiveBlockageCount < 3 ) if( m_recursiveBlockageCount < 3 )
aPath.GetLine().Append( current_obs->hull.NearestPoint( last ) ); aPath.GetLine().Append( current_obs->hull.NearestPoint( last ) );
else { else
{
aPath = aPath.ClipToNearestObstacle( m_world ); aPath = aPath.ClipToNearestObstacle( m_world );
return STUCK; return STUCK;
} }
} }
aPath.NewWalkaround(current_obs->hull, path_pre[0], path_walk[0], path_post[0], aWindingDirection); aPath.NewWalkaround( current_obs->hull, path_pre[0], path_walk[0],
aPath.NewWalkaround(current_obs->hull, path_pre[1], path_walk[1], path_post[1], !aWindingDirection); path_post[0], aWindingDirection );
aPath.NewWalkaround( current_obs->hull, path_pre[1], path_walk[1],
path_post[1], !aWindingDirection );
int len_pre = path_walk[0].Length(); int len_pre = path_walk[0].Length();
int len_alt = path_walk[1].Length(); int len_alt = path_walk[1].Length();
PNS_LINE walk_path( aPath, path_walk[1] ); PNS_LINE walk_path( aPath, path_walk[1] );
bool alt_collides = m_world->CheckColliding(&walk_path, m_solids_only ? PNS_ITEM::SOLID : PNS_ITEM::ANY); bool alt_collides = m_world->CheckColliding( &walk_path,
m_solids_only ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
SHAPE_LINE_CHAIN pnew; SHAPE_LINE_CHAIN pnew;
@ -91,7 +97,9 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
current_obs = nearestObstacle( PNS_LINE( aPath, path_post[1] ) ); current_obs = nearestObstacle( PNS_LINE( aPath, path_post[1] ) );
prev_recursive = false; prev_recursive = false;
} else { }
else
{
pnew = path_pre[0]; pnew = path_pre[0];
pnew.Append( path_walk[0] ); pnew.Append( path_walk[0] );
pnew.Append( path_post[0] ); pnew.Append( path_post[0] );
@ -102,18 +110,21 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
{ {
prev_recursive = false; prev_recursive = false;
current_obs = nearestObstacle( PNS_LINE( aPath, path_post[0] ) ); current_obs = nearestObstacle( PNS_LINE( aPath, path_post[0] ) );
} else }
else
prev_recursive = true; prev_recursive = true;
} }
pnew.Simplify(); pnew.Simplify();
aPath.SetShape( pnew ); aPath.SetShape( pnew );
return IN_PROGRESS; return IN_PROGRESS;
} }
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize )
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath,
PNS_LINE& aWalkPath,
bool aOptimize )
{ {
PNS_LINE path_cw( aInitialPath ), path_ccw( aInitialPath ); PNS_LINE path_cw( aInitialPath ), path_ccw( aInitialPath );
WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
@ -139,22 +150,24 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
int len_cw = path_cw.GetCLine().Length(); int len_cw = path_cw.GetCLine().Length();
int len_ccw = path_ccw.GetCLine().Length(); int len_ccw = path_ccw.GetCLine().Length();
if( m_forceLongerPath ) if( m_forceLongerPath )
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
else else
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
break; break;
} else if(s_cw == DONE && !m_forceLongerPath) { }
else if( s_cw == DONE && !m_forceLongerPath )
{
aWalkPath = path_cw; aWalkPath = path_cw;
break; break;
} else if (s_ccw == DONE && !m_forceLongerPath) { }
else if( s_ccw == DONE && !m_forceLongerPath )
{
aWalkPath = path_ccw; aWalkPath = path_ccw;
break; break;
} }
m_iteration++; m_iteration++;
} }
@ -168,7 +181,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
else else
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
} }
if( m_cursorApproachMode ) if( m_cursorApproachMode )
@ -179,7 +191,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
SHAPE_LINE_CHAIN l = aWalkPath.GetCLine(); SHAPE_LINE_CHAIN l = aWalkPath.GetCLine();
for( int i = 0; i < l.SegmentCount(); i++ ) for( int i = 0; i < l.SegmentCount(); i++ )
{ {
const SEG s = l.Segment( i ); const SEG s = l.Segment( i );
@ -189,8 +200,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
VECTOR2I::extended_type dist_b = (s.b - m_cursorPos).SquaredEuclideanNorm(); VECTOR2I::extended_type dist_b = (s.b - m_cursorPos).SquaredEuclideanNorm();
VECTOR2I::extended_type dist_n = (nearest - m_cursorPos).SquaredEuclideanNorm(); VECTOR2I::extended_type dist_n = (nearest - m_cursorPos).SquaredEuclideanNorm();
if( dist_n <= dist_a && dist_n < dist_b ) if( dist_n <= dist_a && dist_n < dist_b )
{ {
// PNSDisplayDebugLine(l, 3); // PNSDisplayDebugLine(l, 3);
@ -201,6 +210,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
break; break;
} }
} }
if( found ) if( found )
{ {
aWalkPath = aInitialPath; aWalkPath = aInitialPath;
@ -208,7 +218,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
} }
} }
aWalkPath.SetWorld( m_world ); aWalkPath.SetWorld( m_world );
aWalkPath.GetLine().Simplify(); aWalkPath.GetLine().Simplify();
@ -219,3 +228,4 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
return st; return st;
} }

View File

@ -24,22 +24,22 @@
#include "pns_line.h" #include "pns_line.h"
#include "pns_node.h" #include "pns_node.h"
class PNS_WALKAROUND { class PNS_WALKAROUND
{
static const int DefaultIterationLimit = 50; static const int DefaultIterationLimit = 50;
public: public:
PNS_WALKAROUND( PNS_NODE* aWorld ) : PNS_WALKAROUND( PNS_NODE* aWorld ) :
m_world(aWorld), m_iteration_limit(DefaultIterationLimit) { m_world( aWorld ), m_iteration_limit( DefaultIterationLimit )
{
m_forceSingleDirection = false; m_forceSingleDirection = false;
m_forceLongerPath = false; m_forceLongerPath = false;
m_cursorApproachMode = false; m_cursorApproachMode = false;
}; };
~PNS_WALKAROUND() {}; ~PNS_WALKAROUND() {};
enum WalkaroundStatus { enum WalkaroundStatus
{
IN_PROGRESS = 0, IN_PROGRESS = 0,
DONE, DONE,
STUCK STUCK
@ -60,7 +60,6 @@ class PNS_WALKAROUND {
m_solids_only = aSolidsOnly; m_solids_only = aSolidsOnly;
} }
void SetSingleDirection( bool aForceSingleDirection ) void SetSingleDirection( bool aForceSingleDirection )
{ {
m_forceSingleDirection = aForceSingleDirection; m_forceSingleDirection = aForceSingleDirection;
@ -73,8 +72,8 @@ class PNS_WALKAROUND {
m_cursorApproachMode = aEnabled; m_cursorApproachMode = aEnabled;
} }
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize = true); bool aOptimize = true );
private: private:
void start( const PNS_LINE& aInitialPath ); void start( const PNS_LINE& aInitialPath );

View File

@ -1,4 +0,0 @@
You'll see the P&S router sources here, but just not right now.
We are still dealing with some non-technical issues that should be solved by the next week.
Tom

View File

@ -31,25 +31,26 @@
using namespace KiGfx; using namespace KiGfx;
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM *aItem, VIEW_GROUP *aParent ) ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aParent ) :
: EDA_ITEM( NOT_USED ) EDA_ITEM( NOT_USED )
{ {
m_Flags = 0; m_Flags = 0;
m_parent = aParent; m_parent = aParent;
if( aItem ) if( aItem )
Update( aItem ); Update( aItem );
} }
ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM() ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
{ {
} }
void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem ) void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem )
{ {
m_layer = aItem->GetLayers().Start(); m_layer = aItem->GetLayers().Start();
m_color = getLayerColor( m_layer ); m_color = getLayerColor( m_layer );
m_color.a = 0.8; m_color.a = 0.8;
@ -82,12 +83,14 @@ void ROUTER_PREVIEW_ITEM::Update(const PNS_ITEM *aItem)
ViewUpdate( GEOMETRY | APPEARANCE ); ViewUpdate( GEOMETRY | APPEARANCE );
} }
void ROUTER_PREVIEW_ITEM::MarkAsHead() void ROUTER_PREVIEW_ITEM::MarkAsHead()
{ {
if( m_type != PR_VIA ) if( m_type != PR_VIA )
m_color.Saturate( 1.0 ); m_color.Saturate( 1.0 );
} }
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
{ {
BOX2I bbox; BOX2I bbox;
@ -98,40 +101,46 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
bbox = m_line.BBox(); bbox = m_line.BBox();
bbox.Inflate( m_width / 2 ); bbox.Inflate( m_width / 2 );
return bbox; return bbox;
case PR_VIA: case PR_VIA:
bbox = BOX2I( m_viaCenter, VECTOR2I( 0, 0 ) ); bbox = BOX2I( m_viaCenter, VECTOR2I( 0, 0 ) );
bbox.Inflate( m_width / 2 ); bbox.Inflate( m_width / 2 );
return bbox; return bbox;
default: default:
break; break;
} }
return bbox; return bbox;
} }
void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KiGfx::GAL* aGal ) const void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KiGfx::GAL* aGal ) const
{ {
switch( m_type ) switch( m_type )
{ {
case PR_LINE: case PR_LINE:
aGal->SetLayerDepth( -100.0 ); aGal->SetLayerDepth( -100.0 );
aGal->SetLineWidth( m_width ); aGal->SetLineWidth( m_width );
aGal->SetStrokeColor( m_color ); aGal->SetStrokeColor( m_color );
aGal->SetIsStroke( true ); aGal->SetIsStroke( true );
aGal->SetIsFill( false ); aGal->SetIsFill( false );
for( int s = 0; s < m_line.SegmentCount(); s++ ) for( int s = 0; s < m_line.SegmentCount(); s++ )
aGal->DrawLine( m_line.CSegment( s ).a, m_line.CSegment( s ).b ); aGal->DrawLine( m_line.CSegment( s ).a, m_line.CSegment( s ).b );
if( m_line.IsClosed() ) if( m_line.IsClosed() )
aGal->DrawLine( m_line.CSegment( -1 ).b, m_line.CSegment( 0 ).a ); aGal->DrawLine( m_line.CSegment( -1 ).b, m_line.CSegment( 0 ).a );
break; break;
case PR_VIA:
case PR_VIA:
aGal->SetLayerDepth( -101.0 ); aGal->SetLayerDepth( -101.0 );
aGal->SetIsStroke( false ); aGal->SetIsStroke( false );
aGal->SetIsFill( true ); aGal->SetIsFill( true );
aGal->SetFillColor( m_color ); aGal->SetFillColor( m_color );
aGal->DrawCircle( m_viaCenter, m_width / 2 ); aGal->DrawCircle( m_viaCenter, m_width / 2 );
break; break;
default: default:
break; break;
} }
@ -151,6 +160,7 @@ void ROUTER_PREVIEW_ITEM::DebugLine ( const SHAPE_LINE_CHAIN& aLine, int aWidth
#endif #endif
} }
void ROUTER_PREVIEW_ITEM::DebugBox( const BOX2I& aBox, int aStyle ) void ROUTER_PREVIEW_ITEM::DebugBox( const BOX2I& aBox, int aStyle )
{ {
#if 0 #if 0
@ -169,29 +179,52 @@ void ROUTER_PREVIEW_ITEM::DebugBox ( const BOX2I& aBox, int aStyle )
#endif #endif
} }
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor (int layer ) const
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
{ {
// assert (m_view != NULL); // assert (m_view != NULL);
PCB_RENDER_SETTINGS *settings = static_cast <PCB_RENDER_SETTINGS*> (m_parent -> GetView() -> GetPainter() -> GetSettings()); PCB_RENDER_SETTINGS* settings =
return settings->GetLayerColor(layer); static_cast <PCB_RENDER_SETTINGS*> ( m_parent->GetView()->GetPainter()->GetSettings() );
return settings->GetLayerColor( aLayer );
} }
const COLOR4D ROUTER_PREVIEW_ITEM::assignColor ( int style ) const const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
{ {
COLOR4D color; COLOR4D color;
switch(style)
switch( aStyle )
{ {
case 0: color =COLOR4D(0, 1, 0, 1);break; case 0:
case 1: color =COLOR4D(1, 0, 0, 0.3);break; color = COLOR4D( 0, 1, 0, 1 ); break;
case 2: color =COLOR4D(1, 0.5, 0.5, 1);break;
case 3: color =COLOR4D(0, 0, 1, 1);break; case 1:
case 4: color =COLOR4D(1, 1, 1, 1); break; color = COLOR4D( 1, 0, 0, 0.3 ); break;
case 5: color =COLOR4D(1, 1, 0, 1); break;
case 6: color =COLOR4D(0, 1, 1, 1); break; case 2:
case 32: color =COLOR4D(0, 0, 1, 0.5); break; color = COLOR4D( 1, 0.5, 0.5, 1 ); break;
default: break;
case 3:
color = COLOR4D( 0, 0, 1, 1 ); break;
case 4:
color = COLOR4D( 1, 1, 1, 1 ); break;
case 5:
color = COLOR4D( 1, 1, 0, 1 ); break;
case 6:
color = COLOR4D( 0, 1, 1, 1 ); break;
case 32:
color = COLOR4D( 0, 0, 1, 0.5 ); break;
default:
break;
} }
return color; return color;
} }

View File

@ -44,13 +44,15 @@ class PNS_ROUTER;
class ROUTER_PREVIEW_ITEM : public EDA_ITEM class ROUTER_PREVIEW_ITEM : public EDA_ITEM
{ {
public: public:
enum ItemType { enum ItemType
{
PR_VIA, PR_VIA,
PR_LINE, PR_LINE,
PR_STUCK_MARKER PR_STUCK_MARKER
}; };
enum ItemFlags { enum ItemFlags
{
PR_SUGGESTION = 1 PR_SUGGESTION = 1
}; };
@ -62,11 +64,11 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
void StuckMarker( VECTOR2I& aPosition ); void StuckMarker( VECTOR2I& aPosition );
void DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 ); void DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 );
void DebugBox( const BOX2I& aBox, int aStyle = 0 ); void DebugBox( const BOX2I& aBox, int aStyle = 0 );
void Show( int a, std::ostream& b ) const {}; void Show( int a, std::ostream& b ) const {};
const BOX2I ViewBBox() const; const BOX2I ViewBBox() const;
virtual void ViewDraw( int aLayer, KiGfx::GAL* aGal ) const; virtual void ViewDraw( int aLayer, KiGfx::GAL* aGal ) const;
virtual void ViewGetLayers( int aLayers[], int& aCount ) const virtual void ViewGetLayers( int aLayers[], int& aCount ) const
@ -78,9 +80,8 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
void MarkAsHead(); void MarkAsHead();
private: private:
const KiGfx::COLOR4D assignColor( int aStyle ) const;
const KiGfx::COLOR4D assignColor ( int style ) const; const KiGfx::COLOR4D getLayerColor( int aLayer ) const;
const KiGfx::COLOR4D getLayerColor (int layer ) const;
KiGfx::VIEW_GROUP* m_parent; KiGfx::VIEW_GROUP* m_parent;
@ -96,8 +97,7 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
VECTOR2I m_stuckPosition; VECTOR2I m_stuckPosition;
VECTOR2I m_viaCenter; VECTOR2I m_viaCenter;
}; };
#endif #endif

View File

@ -74,7 +74,6 @@ ROUTER_TOOL::~ROUTER_TOOL()
void ROUTER_TOOL::Reset() void ROUTER_TOOL::Reset()
{ {
if( m_router ) if( m_router )
delete m_router; delete m_router;
@ -91,14 +90,18 @@ void ROUTER_TOOL::Reset()
Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) ); Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) );
} }
int ROUTER_TOOL::getDefaultWidth( int aNetCode ) int ROUTER_TOOL::getDefaultWidth( int aNetCode )
{ {
int w, d1, d2; int w, d1, d2;
getNetclassDimensions( aNetCode, w, d1, d2 ); getNetclassDimensions( aNetCode, w, d1, d2 );
return w; return w;
} }
void ROUTER_TOOL::getNetclassDimensions ( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill)
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth,
int& aViaDiameter, int& aViaDrill )
{ {
BOARD* board = getModel<BOARD>( PCB_T ); BOARD* board = getModel<BOARD>( PCB_T );
@ -127,7 +130,8 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
if( aLayer > 0 ) if( aLayer > 0 )
tl = aLayer; tl = aLayer;
PNS_ITEM *picked_seg = NULL, *picked_via = NULL; PNS_ITEM* picked_seg = NULL;
PNS_ITEM* picked_via = NULL;
PNS_ITEMSET candidates = m_router->QueryHoverItems( aWhere ); PNS_ITEMSET candidates = m_router->QueryHoverItems( aWhere );
BOOST_FOREACH( PNS_ITEM* item, candidates.Items() ) BOOST_FOREACH( PNS_ITEM* item, candidates.Items() )
@ -144,7 +148,9 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
{ {
if( item->GetLayers().Overlaps( tl ) || !picked_via ) if( item->GetLayers().Overlaps( tl ) || !picked_via )
picked_via = item; picked_via = item;
} else { }
else
{
if( item->GetLayers().Overlaps( tl ) || !picked_seg ) if( item->GetLayers().Overlaps( tl ) || !picked_seg )
picked_seg = item; picked_seg = item;
} }
@ -163,24 +169,26 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
rv = NULL; rv = NULL;
if( rv ) if( rv )
TRACE(0, "%s, layer : %d, tl: %d", rv->GetKindStr().c_str() % rv->GetLayers().Start() % tl); TRACE( 0, "%s, layer : %d, tl: %d", rv->GetKindStr().c_str() % rv->GetLayers().Start() %
tl );
return rv; return rv;
} }
void ROUTER_TOOL::setMsgPanel( bool aEnabled, int aEntry,
void ROUTER_TOOL::setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage, const wxString& aLowerMessage ) const wxString& aUpperMessage, const wxString& aLowerMessage )
{ {
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> (); PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
if(m_panelItems.size() <= (unsigned int) entry) if( m_panelItems.size() <= (unsigned int) aEntry )
m_panelItems.resize(entry + 1); m_panelItems.resize( aEntry + 1 );
m_panelItems[entry] = MSG_PANEL_ITEM( aUpperMessage, aLowerMessage, BLACK ); m_panelItems[aEntry] = MSG_PANEL_ITEM( aUpperMessage, aLowerMessage, BLACK );
frame->SetMsgPanel( m_panelItems ); frame->SetMsgPanel( m_panelItems );
} }
void ROUTER_TOOL::clearMsgPanel() void ROUTER_TOOL::clearMsgPanel()
{ {
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> (); PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
@ -188,18 +196,20 @@ void ROUTER_TOOL::clearMsgPanel()
frame->ClearMsgPanel(); frame->ClearMsgPanel();
} }
void ROUTER_TOOL::highlightNet(bool enabled, int netcode)
void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode )
{ {
RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings(); RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings();
if(netcode >= 0 && enabled) if( aNetcode >= 0 && aEnabled )
rs->SetHighlight(true, netcode); rs->SetHighlight( true, aNetcode );
else else
rs->SetHighlight( false ); rs->SetHighlight( false );
getView()->UpdateAllLayersColor(); getView()->UpdateAllLayersColor();
} }
void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
{ {
VIEW_CONTROLS* ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
@ -211,8 +221,6 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
VECTOR2I p = aEvent.Position(); VECTOR2I p = aEvent.Position();
startItem = pickSingleItem( p ); startItem = pickSingleItem( p );
if( startItem && startItem->GetNet() >= 0 ) if( startItem && startItem->GetNet() >= 0 )
{ {
bool dummy; bool dummy;
@ -220,13 +228,16 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
ctls->ForceCursorPosition( true, cursorPos ); ctls->ForceCursorPosition( true, cursorPos );
m_startSnapPoint = cursorPos; m_startSnapPoint = cursorPos;
if( startItem->GetLayers().IsMultilayer() ) if( startItem->GetLayers().IsMultilayer() )
m_startLayer = tl; m_startLayer = tl;
else else
m_startLayer = startItem->GetLayers().Start(); m_startLayer = startItem->GetLayers().Start();
m_startItem = startItem; m_startItem = startItem;
} else { }
else
{
m_startItem = NULL; m_startItem = NULL;
m_startSnapPoint = p; m_startSnapPoint = p;
m_startLayer = tl; m_startLayer = tl;
@ -235,6 +246,7 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
} }
} }
void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
{ {
VIEW_CONTROLS* ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
@ -263,21 +275,26 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
ctls->ForceCursorPosition( true, cursorPos ); ctls->ForceCursorPosition( true, cursorPos );
m_endItem = endItem; m_endItem = endItem;
m_endSnapPoint = cursorPos; m_endSnapPoint = cursorPos;
} else { }
else
{
m_endItem = NULL; m_endItem = NULL;
m_endSnapPoint = p; m_endSnapPoint = p;
ctls->ForceCursorPosition( false ); ctls->ForceCursorPosition( false );
} }
if( m_endItem ) if( m_endItem )
TRACE(0, "%s, layer : %d", m_endItem->GetKindStr().c_str() % m_endItem->GetLayers().Start() ); TRACE( 0, "%s, layer : %d", m_endItem->GetKindStr().c_str() %
m_endItem->GetLayers().Start() );
} }
void ROUTER_TOOL::startRouting() void ROUTER_TOOL::startRouting()
{ {
VIEW_CONTROLS* ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 ); int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 );
if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) ) if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) )
width = static_cast<PNS_SEGMENT*>( m_startItem )->GetWidth(); width = static_cast<PNS_SEGMENT*>( m_startItem )->GetWidth();
@ -309,10 +326,13 @@ void ROUTER_TOOL::startRouting ( )
else if( evt->IsClick( MB_Left ) ) else if( evt->IsClick( MB_Left ) )
{ {
updateEndItem( *evt ); updateEndItem( *evt );
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) ) if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
break; break;
m_router->Move( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
} else if (evt->IsKeyUp()) }
else if( evt->IsKeyUp() )
{ {
switch( evt->KeyCode() ) switch( evt->KeyCode() )
{ {
@ -372,7 +392,6 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
if( evt->IsCancel() ) if( evt->IsCancel() )
break; // Finish break; // Finish
else if( evt->IsMotion() ) else if( evt->IsMotion() )
@ -384,7 +403,6 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
} }
} }
// clearMsgPanel(); // clearMsgPanel();
// Restore the default settings // Restore the default settings
@ -394,4 +412,3 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
return 0; return 0;
} }

View File

@ -48,8 +48,8 @@ private:
PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 ); PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
void setMsgPanel( bool enabled, int entry, const wxString& aUpperMessage = wxT(""),
void setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage = wxT(""), const wxString& aLowerMessage = wxT("") ); const wxString& aLowerMessage = wxT("") );
void clearMsgPanel(); void clearMsgPanel();
int getDefaultWidth( int aNetCode ); int getDefaultWidth( int aNetCode );
@ -77,3 +77,4 @@ private:
}; };
#endif #endif

View File

@ -21,7 +21,6 @@
#ifndef __TRACE_H #ifndef __TRACE_H
#define __TRACE_H #define __TRACE_H
#ifdef DEBUG #ifdef DEBUG
#include <string> #include <string>
@ -33,8 +32,6 @@ static void _trace_print(const char *funcName, int level, const std::string& msg
std::cerr << "trace[" << level << "]: " << funcName << ": " << msg << std::endl; std::cerr << "trace[" << level << "]: " << funcName << ": " << msg << std::endl;
} }
#define TRACE( level, fmt, ... ) \ #define TRACE( level, fmt, ... ) \
_trace_print( __FUNCTION__, level, (boost::format( fmt ) % __VA_ARGS__).str() ); _trace_print( __FUNCTION__, level, (boost::format( fmt ) % __VA_ARGS__).str() );