Uncrustified the push&shove source, fixed some warnings.
This commit is contained in:
commit
936e0be090
|
@ -362,7 +362,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
|
|||
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
|
||||
return;
|
||||
|
||||
#ifdef CACHED_CONTAINER_TEST > 0
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
prof_counter totalTime;
|
||||
prof_start( &totalTime, false );
|
||||
#endif
|
||||
|
@ -406,7 +406,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
|
|||
// Add the last one
|
||||
m_freeChunks.insert( std::make_pair( size, offset ) );
|
||||
|
||||
#ifdef CACHED_CONTAINER_TEST > 0
|
||||
#if CACHED_CONTAINER_TEST > 0
|
||||
prof_end( &totalTime );
|
||||
|
||||
wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 );
|
||||
|
|
|
@ -69,7 +69,7 @@ void VIEW_ITEM::ViewRelease()
|
|||
void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const
|
||||
{
|
||||
int* layersPtr = aLayers;
|
||||
for( int i = 0; i < m_layers.size(); ++i )
|
||||
for( unsigned int i = 0; i < m_layers.size(); ++i )
|
||||
{
|
||||
if( m_layers[i] )
|
||||
*layersPtr++ = i;
|
||||
|
|
|
@ -48,3 +48,4 @@ set(PCBNEW_PNS_SRCS
|
|||
)
|
||||
|
||||
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
class DIRECTION_45
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
|
@ -39,7 +38,8 @@ public:
|
|||
* 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.
|
||||
*/
|
||||
enum Directions {
|
||||
enum Directions
|
||||
{
|
||||
N = 0,
|
||||
NE = 1,
|
||||
E = 2,
|
||||
|
@ -55,11 +55,12 @@ public:
|
|||
* Enum AngleType
|
||||
* Represents kind of angle formed by vectors heading in two DIRECTION_45s.
|
||||
*/
|
||||
enum AngleType {
|
||||
ANG_OBTUSE = 0x1,
|
||||
ANG_RIGHT = 0x2,
|
||||
ANG_ACUTE = 0x4,
|
||||
ANG_STRAIGHT = 0x8,
|
||||
enum AngleType
|
||||
{
|
||||
ANG_OBTUSE = 0x01,
|
||||
ANG_RIGHT = 0x02,
|
||||
ANG_ACUTE = 0x04,
|
||||
ANG_STRAIGHT = 0x08,
|
||||
ANG_HALF_FULL = 0x10,
|
||||
ANG_UNDEFINED = 0x20
|
||||
};
|
||||
|
@ -93,16 +94,35 @@ public:
|
|||
{
|
||||
switch( m_dir )
|
||||
{
|
||||
case N : return "north";
|
||||
case NE : return "north-east";
|
||||
case E : return "east";
|
||||
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>";
|
||||
case N:
|
||||
return "north";
|
||||
|
||||
case NE:
|
||||
return "north-east";
|
||||
|
||||
case E:
|
||||
return "east";
|
||||
|
||||
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 )
|
||||
return UNDEFINED;
|
||||
|
||||
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE };
|
||||
return OppositeMap[m_dir];
|
||||
}
|
||||
|
@ -172,7 +193,9 @@ public:
|
|||
* @param aStartDiagonal whether the first segment has to be diagonal
|
||||
* @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 h = abs( aP1.y - aP0.y );
|
||||
|
@ -186,7 +209,9 @@ public:
|
|||
{
|
||||
mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E
|
||||
mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N
|
||||
mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
|
||||
}
|
||||
|
@ -201,6 +226,7 @@ public:
|
|||
SHAPE_LINE_CHAIN pl;
|
||||
|
||||
pl.Append( aP0 );
|
||||
|
||||
if( start_diagonal )
|
||||
pl.Append( aP0 + mp1 );
|
||||
else
|
||||
|
@ -224,15 +250,20 @@ public:
|
|||
const DIRECTION_45 Right() const
|
||||
{
|
||||
DIRECTION_45 r;
|
||||
|
||||
r.m_dir = (Directions) (m_dir + 1);
|
||||
|
||||
if( r.m_dir == NW )
|
||||
r.m_dir = N;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <typename T> int sign(T val) const {
|
||||
template <typename T>
|
||||
int sign( T val ) const
|
||||
{
|
||||
return (T( 0 ) < val) - ( val < T( 0 ) );
|
||||
}
|
||||
|
||||
|
@ -245,12 +276,15 @@ private:
|
|||
void construct( const VECTOR2I& aVec )
|
||||
{
|
||||
m_dir = UNDEFINED;
|
||||
|
||||
if( aVec.x == 0 && aVec.y == 0 )
|
||||
return;
|
||||
|
||||
double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
|
||||
|
||||
if( mag >= 360.0 )
|
||||
mag -= 360.0;
|
||||
|
||||
if( mag < 0.0 )
|
||||
mag += 360.0;
|
||||
|
||||
|
@ -258,10 +292,12 @@ private:
|
|||
|
||||
if( m_dir >= 8 )
|
||||
m_dir = (Directions)( m_dir - 8 );
|
||||
|
||||
if( m_dir < 0 )
|
||||
m_dir = (Directions)( m_dir + 8 );
|
||||
|
||||
return;
|
||||
|
||||
if( aVec.y < 0 )
|
||||
{
|
||||
if( aVec.x > 0 )
|
||||
|
@ -293,3 +329,4 @@ private:
|
|||
};
|
||||
|
||||
#endif // __DIRECTION_H
|
||||
|
||||
|
|
|
@ -37,10 +37,9 @@
|
|||
* overlap and improving search time.
|
||||
**/
|
||||
|
||||
class PNS_INDEX {
|
||||
|
||||
class PNS_INDEX
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::list<PNS_ITEM*> NetItemsList;
|
||||
typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex;
|
||||
typedef boost::unordered_set<PNS_ITEM*> ItemSet;
|
||||
|
@ -54,6 +53,7 @@ public:
|
|||
|
||||
template<class Visitor>
|
||||
int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v );
|
||||
|
||||
template<class Visitor>
|
||||
int Query( const SHAPE* aShape, int aMinDistance, Visitor& v );
|
||||
|
||||
|
@ -64,15 +64,14 @@ public:
|
|||
ItemSet::iterator begin() { return m_allItems.begin(); }
|
||||
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();
|
||||
}
|
||||
|
||||
int Size() const { return m_allItems.size(); }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
static const int MaxSubIndices = 64;
|
||||
static const int SI_Multilayer = 2;
|
||||
static const int SI_SegDiagonal = 0;
|
||||
|
@ -91,11 +90,13 @@ private:
|
|||
ItemSet m_allItems;
|
||||
};
|
||||
|
||||
|
||||
PNS_INDEX::PNS_INDEX()
|
||||
{
|
||||
memset( m_subIndices, 0, sizeof( m_subIndices ) );
|
||||
}
|
||||
|
||||
|
||||
PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
|
||||
{
|
||||
int idx_n = -1;
|
||||
|
@ -107,6 +108,7 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
|
|||
case PNS_ITEM::VIA:
|
||||
idx_n = SI_Multilayer;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SOLID:
|
||||
{
|
||||
if( l.IsMultilayer() )
|
||||
|
@ -115,15 +117,19 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
|
|||
idx_n = SI_PadsTop;
|
||||
else if( l.Start() == 15 )
|
||||
idx_n = SI_PadsBottom;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
case PNS_ITEM::LINE:
|
||||
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert( idx_n >= 0 && idx_n < MaxSubIndices );
|
||||
|
||||
if( !m_subIndices[idx_n] )
|
||||
|
@ -132,23 +138,26 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
|
|||
return m_subIndices[idx_n];
|
||||
}
|
||||
|
||||
|
||||
void PNS_INDEX::Add( PNS_ITEM* aItem )
|
||||
{
|
||||
ItemShapeIndex* idx = getSubindex( aItem );
|
||||
|
||||
|
||||
idx->Add( aItem );
|
||||
m_allItems.insert( aItem );
|
||||
int net = aItem->GetNet();
|
||||
|
||||
if( net >= 0 )
|
||||
{
|
||||
m_netMap[net].push_back( aItem );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_INDEX::Remove( PNS_ITEM* aItem )
|
||||
{
|
||||
ItemShapeIndex* idx = getSubindex( aItem );
|
||||
|
||||
idx->Remove( aItem );
|
||||
m_allItems.erase( aItem );
|
||||
|
||||
|
@ -158,27 +167,30 @@ void PNS_INDEX::Remove( PNS_ITEM *aItem )
|
|||
m_netMap[net].remove( aItem );
|
||||
}
|
||||
|
||||
|
||||
void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
|
||||
{
|
||||
Remove( aOldItem );
|
||||
Add( aNewItem );
|
||||
}
|
||||
|
||||
|
||||
template<class Visitor>
|
||||
int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v )
|
||||
{
|
||||
if( !m_subIndices[index] )
|
||||
return 0;
|
||||
|
||||
return m_subIndices[index]->Query( aShape, aMinDistance, v, false );
|
||||
}
|
||||
|
||||
|
||||
template<class Visitor>
|
||||
int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v )
|
||||
{
|
||||
const SHAPE* shape = aItem->GetShape();
|
||||
int total = 0;
|
||||
|
||||
|
||||
total += querySingle( SI_Multilayer, shape, aMinDistance, v );
|
||||
|
||||
const PNS_LAYERSET layers = aItem->GetLayers();
|
||||
|
@ -188,29 +200,33 @@ template<class Visitor>
|
|||
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
|
||||
total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
|
||||
|
||||
|
||||
for( int i = layers.Start(); i <= layers.End(); ++i )
|
||||
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v );
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int l = layers.Start();
|
||||
|
||||
if( l == 0 )
|
||||
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
|
||||
else if( l == 15 )
|
||||
total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
|
||||
|
||||
total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v );
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
template<class Visitor>
|
||||
int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v )
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
for( int i = 0; i < MaxSubIndices; i++ )
|
||||
total += querySingle( i, aShape, aMinDistance, v );
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -220,22 +236,28 @@ void PNS_INDEX::Clear()
|
|||
for( int i = 0; i < MaxSubIndices; ++i )
|
||||
{
|
||||
ItemShapeIndex* idx = m_subIndices[i];
|
||||
|
||||
if( idx )
|
||||
delete idx;
|
||||
|
||||
m_subIndices[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PNS_INDEX::~PNS_INDEX()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet )
|
||||
{
|
||||
if( m_netMap.find( aNet ) == m_netMap.end() )
|
||||
return NULL;
|
||||
|
||||
return &m_netMap[aNet];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#include "pns_item.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!
|
||||
if( m_net == aOther->m_net )
|
||||
|
@ -36,7 +37,9 @@ bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNee
|
|||
// 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 ) )
|
||||
return true;
|
||||
|
@ -45,28 +48,42 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V
|
|||
if( aOther->m_kind == LINE )
|
||||
{
|
||||
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
const std::string PNS_ITEM::GetKindStr() const
|
||||
{
|
||||
switch( m_kind )
|
||||
{
|
||||
case LINE: return "line";
|
||||
case SEGMENT: return "segment";
|
||||
case VIA: return "via";
|
||||
case JOINT: return "joint";
|
||||
case SOLID: return "solid";
|
||||
default: return "unknown";
|
||||
case LINE:
|
||||
return "line";
|
||||
|
||||
case SEGMENT:
|
||||
return "segment";
|
||||
|
||||
case VIA:
|
||||
return "via";
|
||||
|
||||
case JOINT:
|
||||
return "joint";
|
||||
|
||||
case SOLID:
|
||||
return "solid";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEM::~PNS_ITEM()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -41,11 +41,11 @@ class PNS_NODE;
|
|||
class PNS_ITEM
|
||||
{
|
||||
public:
|
||||
|
||||
static const int UnusedNet = INT_MAX;
|
||||
|
||||
///> Supported item types
|
||||
enum PnsKind {
|
||||
enum PnsKind
|
||||
{
|
||||
SOLID = 1,
|
||||
LINE = 2,
|
||||
JOINT = 4,
|
||||
|
@ -88,8 +88,6 @@ public:
|
|||
return SHAPE_LINE_CHAIN();
|
||||
};
|
||||
|
||||
|
||||
|
||||
PnsKind GetKind() const { return m_kind; }
|
||||
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; }
|
||||
|
||||
|
@ -106,7 +104,10 @@ public:
|
|||
///> Layers accessors
|
||||
const PNS_LAYERSET& GetLayers() const { return m_layers; }
|
||||
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.
|
||||
void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; }
|
||||
|
@ -117,29 +118,31 @@ public:
|
|||
void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; }
|
||||
PNS_NODE* GetWorld() const { return m_world; }
|
||||
|
||||
|
||||
///> 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
|
||||
/// collision if needed.
|
||||
virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const;
|
||||
/// aClearance and returns true if so. It can also calculate a minimum translation vector that
|
||||
/// resolves the collision if needed.
|
||||
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||
VECTOR2I& aMTV ) const;
|
||||
|
||||
///> A shortcut without MTV calculation
|
||||
bool Collide( const PNS_ITEM* aOther, int aClearance ) const
|
||||
{
|
||||
VECTOR2I dummy;
|
||||
|
||||
return Collide( aOther, aClearance, false, dummy );
|
||||
}
|
||||
|
||||
///> Returns the geometric shape of the item
|
||||
virtual const SHAPE* GetShape() const {
|
||||
virtual const SHAPE* GetShape() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
PnsKind m_kind;
|
||||
|
||||
BOARD_ITEM* m_parent;
|
||||
|
@ -151,5 +154,5 @@ protected:
|
|||
int m_net;
|
||||
};
|
||||
|
||||
#endif // __PNS_ITEM_H
|
||||
#endif // __PNS_ITEM_Ha
|
||||
|
||||
|
|
|
@ -25,48 +25,57 @@
|
|||
|
||||
PNS_ITEMSET::PNS_ITEMSET()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET::~PNS_ITEMSET()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
|
||||
{
|
||||
ItemVector newItems;
|
||||
PNS_LAYERSET l;
|
||||
|
||||
if( aEnd < 0 )
|
||||
l = PNS_LAYERSET( aStart );
|
||||
else
|
||||
l = PNS_LAYERSET( aStart, aEnd );
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
|
||||
if( item->GetLayers().Overlaps( l ) )
|
||||
newItems.push_back( item );
|
||||
|
||||
m_items = newItems;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
|
||||
{
|
||||
ItemVector newItems;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
|
||||
if( item->GetKind() & aKindMask )
|
||||
newItems.push_back( item );
|
||||
|
||||
m_items = newItems;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
|
||||
{
|
||||
ItemVector newItems;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
|
||||
if( item->GetNet() == aNet )
|
||||
newItems.push_back( item );
|
||||
|
||||
m_items = newItems;
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
/**
|
||||
* 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
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::vector<PNS_ITEM*> ItemVector;
|
||||
|
||||
PNS_ITEMSET();
|
||||
|
@ -60,3 +60,4 @@ private:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,18 +32,20 @@
|
|||
/**
|
||||
* Class PNS_JOINT
|
||||
*
|
||||
* Represents a 2D point on a given set of layers and belonging to a certain 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.
|
||||
* Represents a 2D point on a given set of layers and belonging to a certain
|
||||
* 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.
|
||||
**/
|
||||
|
||||
class PNS_JOINT : public PNS_ITEM
|
||||
{
|
||||
public:
|
||||
typedef std::vector<PNS_ITEM*> LinkedItems;
|
||||
|
||||
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed
|
||||
struct HashTag {
|
||||
///> Joints are hashed by their position, layers and net.
|
||||
/// Linked items are, obviously, not hashed
|
||||
struct HashTag
|
||||
{
|
||||
VECTOR2I pos;
|
||||
int net;
|
||||
};
|
||||
|
@ -51,7 +53,8 @@ public:
|
|||
PNS_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 )
|
||||
{
|
||||
m_tag.pos = aPos;
|
||||
|
@ -75,28 +78,33 @@ public:
|
|||
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
|
||||
{
|
||||
if( m_linkedItems.size() != 2 )
|
||||
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;
|
||||
|
||||
PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]);
|
||||
PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]);
|
||||
|
||||
// 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)
|
||||
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() )
|
||||
return;
|
||||
|
||||
m_linkedItems.push_back( aItem );
|
||||
}
|
||||
|
||||
|
@ -104,10 +112,13 @@ public:
|
|||
///> Returns true if the joint became dangling after unlinking.
|
||||
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() )
|
||||
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
|
||||
|
@ -130,9 +141,12 @@ public:
|
|||
int LinkCount( int aMask = -1 ) const
|
||||
{
|
||||
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 )
|
||||
n++;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
@ -151,17 +165,18 @@ public:
|
|||
m_layers.Merge( aJoint.m_layers );
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
///> hash tag for unordered_multimap
|
||||
HashTag m_tag;
|
||||
|
||||
|
@ -171,18 +186,22 @@ private:
|
|||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine( seed, p.pos.x );
|
||||
boost::hash_combine( seed, p.pos.y );
|
||||
boost::hash_combine( seed, p.net );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif // __PNS_JOINT_H
|
||||
|
||||
|
|
|
@ -28,11 +28,9 @@
|
|||
*
|
||||
* Represents a contiguous set of PCB layers.
|
||||
*/
|
||||
|
||||
class PNS_LAYERSET
|
||||
{
|
||||
public:
|
||||
|
||||
PNS_LAYERSET() :
|
||||
m_start( -1 ),
|
||||
m_end( -1 )
|
||||
|
@ -42,6 +40,7 @@ class PNS_LAYERSET
|
|||
{
|
||||
if( aStart > aEnd )
|
||||
std::swap( aStart, aEnd );
|
||||
|
||||
m_start = aStart;
|
||||
m_end = aEnd;
|
||||
}
|
||||
|
@ -80,11 +79,13 @@ class PNS_LAYERSET
|
|||
return m_start != m_end;
|
||||
}
|
||||
|
||||
int Start() const {
|
||||
int Start() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
int End() const {
|
||||
int End() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
|
@ -99,6 +100,7 @@ class PNS_LAYERSET
|
|||
|
||||
if( aOther.m_start < m_start )
|
||||
m_start = aOther.m_start;
|
||||
|
||||
if( aOther.m_end > m_end )
|
||||
m_end = aOther.m_end;
|
||||
}
|
||||
|
@ -110,9 +112,9 @@ class PNS_LAYERSET
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_start;
|
||||
int m_end;
|
||||
};
|
||||
|
||||
#endif // __PNS_LAYERSET_H
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
|
||||
#include "pns_line.h"
|
||||
#include "pns_node.h"
|
||||
#include "pns_via.h"
|
||||
|
@ -49,6 +48,7 @@ PNS_LINE *PNS_LINE::Clone() const
|
|||
return l;
|
||||
}
|
||||
|
||||
|
||||
PNS_LINE* PNS_LINE::CloneProperties() const
|
||||
{
|
||||
PNS_LINE* l = new PNS_LINE();
|
||||
|
@ -61,9 +61,11 @@ PNS_LINE *PNS_LINE::CloneProperties() const
|
|||
return l;
|
||||
}
|
||||
|
||||
|
||||
PNS_SEGMENT* PNS_SEGMENT::Clone() const
|
||||
{
|
||||
PNS_SEGMENT* s = new PNS_SEGMENT;
|
||||
|
||||
s->m_width = m_width;
|
||||
s->m_net = m_net;
|
||||
s->m_shape = m_shape;
|
||||
|
@ -72,6 +74,7 @@ PNS_SEGMENT *PNS_SEGMENT::Clone() const
|
|||
return s; // assert(false);
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
bool PNS_LINE::MergeObtuseSegments()
|
||||
{
|
||||
|
@ -90,6 +93,7 @@ bool PNS_LINE::MergeObtuseSegments( )
|
|||
iter++;
|
||||
int n_segs = current_path.SegmentCount();
|
||||
int max_step = n_segs - 2;
|
||||
|
||||
if( step > max_step )
|
||||
step = max_step;
|
||||
|
||||
|
@ -116,7 +120,9 @@ bool PNS_LINE::MergeObtuseSegments( )
|
|||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
}
|
||||
|
@ -140,6 +146,7 @@ bool PNS_LINE::MergeObtuseSegments( )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -150,12 +157,15 @@ bool PNS_LINE::MergeObtuseSegments( )
|
|||
m_line = current_path;
|
||||
return m_line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
step--;
|
||||
}
|
||||
}
|
||||
|
||||
return m_line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE::MergeSegments()
|
||||
{
|
||||
int step = m_line.PointCount() - 3;
|
||||
|
@ -173,6 +183,7 @@ bool PNS_LINE::MergeSegments( )
|
|||
iter++;
|
||||
int n_segs = current_path.SegmentCount();
|
||||
int max_step = n_segs - 2;
|
||||
|
||||
if( step > max_step )
|
||||
step = max_step;
|
||||
|
||||
|
@ -193,11 +204,12 @@ bool PNS_LINE::MergeSegments( )
|
|||
|
||||
if( n > 0 )
|
||||
{
|
||||
SHAPE_LINE_CHAIN path_straight = DIRECTION_45().BuildInitialTrace(s1.a, s2.a, false);
|
||||
SHAPE_LINE_CHAIN path_diagonal = DIRECTION_45().BuildInitialTrace(s1.a, s2.a, true);
|
||||
|
||||
|
||||
|
||||
SHAPE_LINE_CHAIN path_straight = DIRECTION_45().BuildInitialTrace( s1.a,
|
||||
s2.a,
|
||||
false );
|
||||
SHAPE_LINE_CHAIN path_diagonal = DIRECTION_45().BuildInitialTrace( s1.a,
|
||||
s2.a,
|
||||
true );
|
||||
}
|
||||
|
||||
if( DIRECTION_45( s1 ) == DIRECTION_45( s2 ) )
|
||||
|
@ -219,10 +231,7 @@ bool PNS_LINE::MergeSegments( )
|
|||
found_anything = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if( DIRECTION_45( s1 ).IsObtuse( DIRECTION_45( s2 ) ) )
|
||||
{
|
||||
|
@ -232,7 +241,9 @@ bool PNS_LINE::MergeSegments( )
|
|||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
}
|
||||
|
@ -255,8 +266,8 @@ bool PNS_LINE::MergeSegments( )
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -267,18 +278,20 @@ bool PNS_LINE::MergeSegments( )
|
|||
m_line = current_path;
|
||||
return m_line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
step--;
|
||||
}
|
||||
}
|
||||
|
||||
return m_line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int PNS_LINE::CountCorners( int aAngles )
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for( int i = 0; i < m_line.SegmentCount() - 1; i++ )
|
||||
{
|
||||
const SEG seg1 = m_line.CSegment( i );
|
||||
|
@ -288,12 +301,15 @@ int PNS_LINE::CountCorners(int aAngles)
|
|||
const DIRECTION_45 dir2( seg2 );
|
||||
|
||||
DIRECTION_45::AngleType a = dir1.Angle( dir2 );
|
||||
|
||||
if( a & aAngles )
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// #define DUMP_TEST_CASES
|
||||
|
||||
// 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,
|
||||
bool aCw ) const
|
||||
{
|
||||
|
||||
typedef SHAPE_LINE_CHAIN::Intersection Intersection;
|
||||
|
||||
SHAPE_LINE_CHAIN l_orig( m_line );
|
||||
|
@ -323,14 +338,14 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|||
#endif
|
||||
|
||||
aObstacle.Intersect( m_line, isects );
|
||||
|
||||
// printf("NewWalk intersectiosn :%d\n" ,isects.size());
|
||||
if( !aCw )
|
||||
l_hull = aObstacle.Reverse();
|
||||
else
|
||||
l_hull = aObstacle;
|
||||
|
||||
BOOST_FOREACH( Intersection isect, isects )
|
||||
{
|
||||
BOOST_FOREACH( Intersection isect, isects ) {
|
||||
l_orig.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 );
|
||||
}
|
||||
|
||||
|
||||
for( int i = l_orig.PointCount() - 1; i >= 1; i-- )
|
||||
if( inside[i] && outside[i - 1] )
|
||||
{
|
||||
|
@ -375,7 +389,8 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|||
{
|
||||
l_orig.Remove( i, -1 );
|
||||
// n = i;
|
||||
} else if(!inside[i])
|
||||
}
|
||||
else if( !inside[i] )
|
||||
break;
|
||||
|
||||
if( !outside.size() && on_edge.size() < 2 )
|
||||
|
@ -389,16 +404,19 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|||
{
|
||||
if( last_pre < 0 )
|
||||
aPrePath.Append( p );
|
||||
|
||||
path.Append( p );
|
||||
}
|
||||
else if( on_edge[i] )
|
||||
{
|
||||
int li = -1;
|
||||
|
||||
if( last_pre < 0 )
|
||||
{
|
||||
aPrePath.Append( p );
|
||||
last_pre = path.PointCount();
|
||||
}
|
||||
|
||||
if( i == l_orig.PointCount() - 1 || outside[i + 1] )
|
||||
{
|
||||
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 ) );
|
||||
|
||||
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 ) );
|
||||
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;
|
||||
}
|
||||
|
||||
if(li >= 0) {
|
||||
if( li >= 0 )
|
||||
{
|
||||
if( i >= li )
|
||||
break;
|
||||
else {
|
||||
else
|
||||
i = li;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
first_post = path.PointCount() - 1;
|
||||
}
|
||||
|
@ -433,12 +456,14 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
|||
return;
|
||||
|
||||
aWalkaroundPath = path.Slice( last_pre, first_post );
|
||||
|
||||
if( first_post >= 0 )
|
||||
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 );
|
||||
|
||||
|
@ -462,15 +487,23 @@ bool PNS_LINE::onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, boo
|
|||
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();
|
||||
|
||||
for( int i = 0; i < line.SegmentCount(); 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 s( tmp.a, tmp.b );
|
||||
|
||||
if( reverse )
|
||||
{
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -505,10 +540,16 @@ bool PNS_LINE::walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &ob
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
VECTOR2I ip_start;
|
||||
|
@ -521,11 +562,18 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
|
|||
if( line.SegmentCount() < 1 )
|
||||
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;
|
||||
|
||||
// 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");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
pre = line.Slice( 0, index_l_start );
|
||||
pre.Append( ip_start );
|
||||
walk.Clear();
|
||||
|
@ -555,10 +602,13 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
|
|||
break;
|
||||
|
||||
is++;
|
||||
|
||||
if( is == obstacle.PointCount() )
|
||||
is = 0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int is = index_o_start;
|
||||
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 );
|
||||
walk.Append( obstacle.CPoint( is ) );
|
||||
|
||||
if( is == ie )
|
||||
break;
|
||||
|
||||
is--;
|
||||
|
||||
if( is < 0 )
|
||||
is = obstacle.PointCount() - 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
walk.Append( ip_end );
|
||||
|
@ -591,27 +641,28 @@ bool PNS_LINE::Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAP
|
|||
// }
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
||||
SHAPE_LINE_CHAIN& aPath,
|
||||
bool aCw ) const
|
||||
{
|
||||
SHAPE_LINE_CHAIN walk, post;
|
||||
|
||||
NewWalkaround( aObstacle, aPath, walk, post, aCw );
|
||||
aPath.Append( walk );
|
||||
aPath.Append( post );
|
||||
aPath.Simplify();
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
||||
SHAPE_LINE_CHAIN& aPath,
|
||||
bool aCw ) const
|
||||
{
|
||||
SHAPE_LINE_CHAIN walk, post;
|
||||
|
||||
Walkaround( aObstacle, aPath, walk, post, aCw );
|
||||
aPath.Append( walk );
|
||||
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 ds = dir.Perpendicular().Resize( x / 2 );
|
||||
VECTOR2I pd = dir.Resize( x / 2 );
|
||||
VECTOR2I dp = dir.Resize( d );
|
||||
|
||||
|
||||
SHAPE_LINE_CHAIN s;
|
||||
|
||||
s.SetClosed( true );
|
||||
|
||||
s.Append( b + p0 + pd );
|
||||
|
@ -654,7 +704,6 @@ const SHAPE_LINE_CHAIN PNS_SEGMENT::Hull(int aClearance, int aWalkaroundThicknes
|
|||
return s.Reverse();
|
||||
else
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -664,18 +713,23 @@ bool PNS_LINE::Is45Degree()
|
|||
{
|
||||
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 )
|
||||
angle += 360.0;
|
||||
|
||||
double angle_a = fabs( fmod( angle, 45.0 ) );
|
||||
|
||||
if( angle_a > 1.0 && angle_a < 44.0 )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const
|
||||
{
|
||||
PNS_LINE l( *this );
|
||||
|
@ -692,6 +746,7 @@ const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE *aNode ) const
|
|||
return l;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::ShowLinks()
|
||||
{
|
||||
if( !m_segmentRefs )
|
||||
|
@ -699,6 +754,10 @@ void PNS_LINE::ShowLinks()
|
|||
printf( "line %p: no links\n", this );
|
||||
return;
|
||||
}
|
||||
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]) ;
|
||||
|
||||
printf( "line %p: %d linked segs\n", this, (int)m_segmentRefs->size() );
|
||||
|
||||
for( int i = 0; i < (int) m_segmentRefs->size(); i++ )
|
||||
printf( "seg %d: %p\n", i, (*m_segmentRefs)[i] );
|
||||
}
|
||||
|
||||
|
|
|
@ -38,15 +38,18 @@ class PNS_VIA;
|
|||
/**
|
||||
* Class PNS_LINE
|
||||
*
|
||||
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,
|
||||
* junctions between multiple traces or two traces different widths and combinations of these).
|
||||
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on
|
||||
* a via/pad/segment that belongs/begins them.
|
||||
* Represents a track on a PCB, connecting two non-trivial joints (that is,
|
||||
* vias, pads, junctions between multiple traces or two traces different widths
|
||||
* and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
|
||||
* 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
|
||||
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends.
|
||||
* PNS_LINEs can be either loose (consisting of segments that do not belong to
|
||||
* 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
|
||||
|
@ -71,7 +74,6 @@ public:
|
|||
m_hasVia = false;
|
||||
m_affectedRangeStart = -1;
|
||||
SetLayer( aLayer );
|
||||
|
||||
}
|
||||
|
||||
PNS_LINE( const PNS_LINE& aOther ) :
|
||||
|
@ -114,7 +116,8 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
int GetLayer() const { return GetLayers().Start(); }
|
||||
|
@ -134,11 +137,12 @@ public:
|
|||
{
|
||||
if( !m_segmentRefs )
|
||||
m_segmentRefs = new std::vector<PNS_SEGMENT*> ();
|
||||
|
||||
m_segmentRefs->push_back( aSeg );
|
||||
}
|
||||
|
||||
///> Returns a list of segments from the owning node that constitute this line (or NULL if
|
||||
///> the line is loose)
|
||||
///> Returns a list of segments from the owning node that constitute this
|
||||
///> line (or NULL if the line is loose)
|
||||
LinkedSegments* GetLinkedSegments()
|
||||
{
|
||||
return m_segmentRefs;
|
||||
|
@ -149,10 +153,12 @@ public:
|
|||
if( !m_segmentRefs )
|
||||
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;
|
||||
|
||||
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
|
||||
|
@ -162,8 +168,8 @@ public:
|
|||
///> Returns the number of corners of angles specified by mask aAngles.
|
||||
int CountCorners( int aAngles );
|
||||
|
||||
|
||||
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle).
|
||||
///> Calculates a line thightly wrapping a convex hull
|
||||
///> of an obstacle object (aObstacle).
|
||||
///> aPrePath = path from origin to the obstacle
|
||||
///> aWalkaroundPath = path around the obstacle
|
||||
///> aPostPath = past from obstacle till the end
|
||||
|
@ -179,13 +185,16 @@ public:
|
|||
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,
|
||||
SHAPE_LINE_CHAIN& aPath,
|
||||
bool aCw ) const;
|
||||
|
||||
|
||||
bool Is45Degree();
|
||||
|
||||
///> Prints out all linked segments
|
||||
|
@ -193,7 +202,8 @@ public:
|
|||
|
||||
bool EndsWithVia() const { return m_hasVia; }
|
||||
|
||||
void AppendVia ( const PNS_VIA &aVia ) {
|
||||
void AppendVia( const PNS_VIA& aVia )
|
||||
{
|
||||
m_hasVia = true;
|
||||
m_via = aVia;
|
||||
m_via.SetNet( m_net );
|
||||
|
@ -220,7 +230,9 @@ public:
|
|||
aStart = m_affectedRangeStart;
|
||||
aEnd = m_affectedRangeEnd;
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
aStart = 0;
|
||||
aEnd = m_line.PointCount();
|
||||
return false;
|
||||
|
@ -229,7 +241,8 @@ public:
|
|||
|
||||
private:
|
||||
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.
|
||||
LinkedSegments* m_segmentRefs;
|
||||
|
@ -238,6 +251,7 @@ private:
|
|||
SHAPE_LINE_CHAIN m_line;
|
||||
|
||||
int m_width;
|
||||
|
||||
///> Via at the end and a flag indicating if it's enabled.
|
||||
PNS_VIA m_via;
|
||||
bool m_hasVia;
|
||||
|
@ -246,6 +260,5 @@ private:
|
|||
int m_affectedRangeEnd;
|
||||
};
|
||||
|
||||
|
||||
#endif // __PNS_LINE_H
|
||||
|
||||
|
|
|
@ -46,12 +46,14 @@ PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_NODE *aWorld )
|
|||
m_shove = NULL;
|
||||
};
|
||||
|
||||
|
||||
PNS_LINE_PLACER::~PNS_LINE_PLACER()
|
||||
{
|
||||
if( m_shove )
|
||||
delete m_shove;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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_tail.SetNet( aNet );
|
||||
m_head.SetWidth( aWidth );
|
||||
|
@ -83,6 +88,7 @@ void PNS_LINE_PLACER::StartPlacement(const VECTOR2I& aStart, int aNet, int aWidt
|
|||
m_placingVia = false;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::SetInitialDirection( const DIRECTION_45& aDirection )
|
||||
{
|
||||
m_initial_direction = aDirection;
|
||||
|
@ -91,13 +97,7 @@ void PNS_LINE_PLACER::SetInitialDirection(const DIRECTION_45& 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()
|
||||
{
|
||||
SHAPE_LINE_CHAIN::Intersections ips;
|
||||
|
@ -141,7 +141,9 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
|
|||
tail.Clear();
|
||||
head.Clear();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clip till the last tail segment before intersection.
|
||||
// Set the direction to the one of this segment.
|
||||
const SEG last = tail.CSegment( n - 1 );
|
||||
|
@ -150,16 +152,11 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
|
|||
tail.Remove( n, -1 );
|
||||
return true;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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::AngleType angle = first_head.Angle( last_tail );
|
||||
|
||||
// case 1: we have a defined routing direction, and the currently computed head
|
||||
// goes in different one.
|
||||
// case 1: we have a defined routing direction, and the currently computed
|
||||
// head goes in different one.
|
||||
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
|
||||
// an acute or right angle, reduce the tail by one segment (and hope that further iterations)
|
||||
// will result with a cleaner trace
|
||||
bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE);
|
||||
// case 2: regardless of the current routing direction, if the tail/head
|
||||
// extremities form an acute or right angle, reduce the tail by one segment
|
||||
// (and hope that further iterations) will result with a cleaner trace
|
||||
bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT ||
|
||||
angle == DIRECTION_45::ANG_ACUTE);
|
||||
|
||||
if( pullback_1 || pullback_2 )
|
||||
{
|
||||
|
||||
const SEG last = tail.CSegment( -1 );
|
||||
m_direction = DIRECTION_45( last );
|
||||
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 result with a head
|
||||
// trace that starts with a segment following our current direction.
|
||||
// erase the last point in the tail, hoping that the next iteration will
|
||||
// result with a head trace that starts with a segment following our
|
||||
// current direction.
|
||||
if( n < 2 )
|
||||
tail.Clear(); // don't leave a single-point tail
|
||||
else
|
||||
|
@ -214,14 +213,7 @@ bool PNS_LINE_PLACER::handlePullback()
|
|||
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 )
|
||||
{
|
||||
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 );
|
||||
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 );
|
||||
|
||||
PNS_LINE tmp( m_tail, replacement );
|
||||
|
@ -265,7 +258,6 @@ bool PNS_LINE_PLACER::reduceTail(const VECTOR2I& aEnd)
|
|||
|
||||
if( reduce_index >= 0 )
|
||||
{
|
||||
|
||||
TRACE( 0, "Placer: reducing tail: %d", reduce_index );
|
||||
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
|
||||
{
|
||||
const DIRECTION_45 dir_a( a );
|
||||
const DIRECTION_45 dir_b( 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()
|
||||
{
|
||||
SHAPE_LINE_CHAIN& head = m_head.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();
|
||||
tail.Simplify();
|
||||
|
@ -338,6 +321,7 @@ bool PNS_LINE_PLACER::mergeHead()
|
|||
if( n_tail )
|
||||
{
|
||||
dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
|
||||
|
||||
if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
|
||||
return false;
|
||||
}
|
||||
|
@ -357,18 +341,17 @@ bool PNS_LINE_PLACER::mergeHead()
|
|||
m_p_start = last.b;
|
||||
m_direction = DIRECTION_45( last ).Right();
|
||||
|
||||
|
||||
head.Remove( 0, n_head - 2 );
|
||||
|
||||
TRACE( 0, "Placer: merge %d, new direction: %s", n_head % m_direction.Format().c_str() );
|
||||
|
||||
|
||||
head.Simplify();
|
||||
tail.Simplify();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
|
||||
{
|
||||
if( !m_placingVia )
|
||||
|
@ -381,10 +364,11 @@ bool PNS_LINE_PLACER::handleViaPlacement ( PNS_LINE& aHead )
|
|||
VECTOR2I force;
|
||||
VECTOR2I lead = aHead.GetCLine().CPoint( -1 ) - aHead.GetCLine().CPoint( 0 );
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
v.SetPos( v.GetPos() + force );
|
||||
|
@ -394,15 +378,9 @@ bool PNS_LINE_PLACER::handleViaPlacement ( PNS_LINE& aHead )
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround)
|
||||
|
||||
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...
|
||||
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 walkFull, walkSolids;
|
||||
|
||||
|
||||
if( m_mode == RM_Ignore )
|
||||
{
|
||||
aNewHead = initTrack;
|
||||
return true;
|
||||
}
|
||||
|
||||
handleViaPlacement( initTrack );
|
||||
|
||||
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());
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
#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( "total cost: walk cor %.0f len %.0f orig cor %.0f len %.0f walk-better %d\n",
|
||||
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 );
|
||||
#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;
|
||||
else if( stat_solids == PNS_WALKAROUND::DONE )
|
||||
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 )
|
||||
{
|
||||
|
||||
optimizer.SetWorld( m_currentNode );
|
||||
optimizer.ClearCache();
|
||||
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;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
walkaround.SetWorld( m_currentNode );
|
||||
walkaround.SetSolidsOnly( false );
|
||||
walkaround.SetIterationLimit( 10 );
|
||||
|
@ -534,20 +516,12 @@ bool PNS_LINE_PLACER::routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCw
|
|||
|
||||
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()
|
||||
{
|
||||
SHAPE_LINE_CHAIN& head = m_head.GetLine();
|
||||
|
@ -568,12 +542,12 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
|
|||
|
||||
PNS_LINE new_head( m_tail, opt_line );
|
||||
|
||||
// and see if it could be made simpler by merging obtuse/collnear segments. If so,
|
||||
// replace the (threshold) last tail points and the head with the optimized line
|
||||
// and see if it could be made simpler by merging obtuse/collnear segments.
|
||||
// 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( new_head.MergeSegments() )
|
||||
{
|
||||
PNS_LINE tmp( m_tail, opt_line );
|
||||
|
@ -593,14 +567,6 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
|
|||
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 )
|
||||
{
|
||||
|
@ -613,11 +579,12 @@ void PNS_LINE_PLACER::routeStep(const VECTOR2I& aP)
|
|||
|
||||
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++ )
|
||||
{
|
||||
|
||||
if( !go_back && m_follow_mouse )
|
||||
reduceTail( aP );
|
||||
|
||||
|
@ -651,20 +618,12 @@ void PNS_LINE_PLACER::routeStep(const VECTOR2I& aP)
|
|||
{
|
||||
if( optimizeTailHeadTransition() )
|
||||
return;
|
||||
|
||||
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 )
|
||||
{
|
||||
if( m_smooth_mouse )
|
||||
|
@ -680,9 +639,9 @@ bool PNS_LINE_PLACER::Route(const VECTOR2I& aP)
|
|||
p_cur += step;
|
||||
|
||||
routeStep( p_cur );
|
||||
|
||||
} while( p_cur != aP );
|
||||
} else
|
||||
}
|
||||
else
|
||||
routeStep( aP );
|
||||
|
||||
return CurrentEnd() == aP;
|
||||
|
@ -692,24 +651,30 @@ bool PNS_LINE_PLACER::Route(const VECTOR2I& aP)
|
|||
const PNS_LINE PNS_LINE_PLACER::GetTrace() const
|
||||
{
|
||||
PNS_LINE tmp( m_head );
|
||||
|
||||
tmp.SetShape( m_tail.GetCLine() );
|
||||
tmp.GetLine().Append( m_head.GetCLine() );
|
||||
tmp.GetLine().Simplify();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::FlipPosture()
|
||||
{
|
||||
m_initial_direction = m_initial_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 );
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE* PNS_LINE_PLACER::GetCurrentNode() const
|
||||
{
|
||||
return m_shove->GetCurrentNode();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ class PNS_ROUTER_BASE;
|
|||
/**
|
||||
* 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
|
||||
|
@ -59,7 +60,16 @@ class PNS_LINE_PLACER
|
|||
///> Starts placement of a line at point aStart.
|
||||
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 );
|
||||
|
||||
///> Sets initial routing direction/posture
|
||||
|
@ -67,15 +77,18 @@ class PNS_LINE_PLACER
|
|||
|
||||
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; }
|
||||
///> 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; }
|
||||
|
||||
///> Returns the whole routed line
|
||||
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
|
||||
{
|
||||
if( m_head.GetCLine().PointCount() > 0 )
|
||||
|
@ -86,10 +99,10 @@ class PNS_LINE_PLACER
|
|||
return m_p_start;
|
||||
}
|
||||
|
||||
|
||||
///> Returns all items in the world that have been affected by the routing operation. Used
|
||||
/// to update data structures of the host application
|
||||
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded);
|
||||
///> Returns all items in the world that have been affected by the routing
|
||||
///> operation. Used to update data structures of the host application
|
||||
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
|
||||
PNS_NODE::ItemVector& aAdded );
|
||||
|
||||
///> Toggles the current posture (straight/diagonal) of the trace head.
|
||||
void FlipPosture();
|
||||
|
@ -98,59 +111,145 @@ class PNS_LINE_PLACER
|
|||
PNS_NODE* GetCurrentNode() const;
|
||||
|
||||
private:
|
||||
|
||||
static const double m_shoveLengthThreshold = 1.7;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
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 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 );
|
||||
|
||||
///> routing mode (walkaround, shove, etc.)
|
||||
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;
|
||||
|
||||
///> mouse smoothing active
|
||||
bool m_smooth_mouse;
|
||||
|
||||
///> mouse smoothing step (in world units)
|
||||
int m_smoothing_step;
|
||||
|
||||
///> current routing direction
|
||||
DIRECTION_45 m_direction;
|
||||
|
||||
///> routing direction for new traces
|
||||
DIRECTION_45 m_initial_direction;
|
||||
|
||||
///> routing "head": volatile part of the track from the previously
|
||||
/// analyzed point to the current routing destination
|
||||
PNS_LINE m_head;
|
||||
|
||||
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
|
||||
PNS_LINE m_tail;
|
||||
|
||||
///> current algorithm iteration
|
||||
int m_iteration;
|
||||
|
||||
///> pointer to world to search colliding items
|
||||
PNS_NODE* m_world;
|
||||
|
||||
///> current routing start point (end of tail, beginning of head)
|
||||
VECTOR2I m_p_start;
|
||||
|
||||
///> The shove engine
|
||||
PNS_SHOVE* m_shove;
|
||||
|
||||
///> Current world state
|
||||
PNS_NODE* m_currentNode;
|
||||
|
||||
///> Are we placing a via?
|
||||
bool m_placingVia;
|
||||
|
||||
///> current via diameter
|
||||
int m_viaDiameter;
|
||||
|
||||
///> current via drill
|
||||
int m_viaDrill;
|
||||
|
||||
///> walkaround algorithm iteration limit
|
||||
int m_walkaroundIterationLimit;
|
||||
|
||||
///> smart pads optimizer enabled.
|
||||
bool m_smartPads;
|
||||
};
|
||||
|
||||
#endif // __PNS_LINE_PLACER_H
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ PNS_NODE::PNS_NODE()
|
|||
allocNodes.insert( this );
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE::~PNS_NODE()
|
||||
{
|
||||
if( !m_children.empty() )
|
||||
|
@ -70,7 +71,8 @@ PNS_NODE::~PNS_NODE()
|
|||
|
||||
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 ) )
|
||||
delete *i;
|
||||
|
||||
|
@ -98,39 +100,46 @@ int PNS_NODE::GetClearance(const PNS_ITEM *a, const PNS_ITEM *b) const
|
|||
return clearance;
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE* PNS_NODE::Branch()
|
||||
{
|
||||
PNS_NODE* child = new PNS_NODE;
|
||||
|
||||
m_children.push_back( child );
|
||||
|
||||
child->m_parent = this;
|
||||
child->m_clearanceFunctor = m_clearanceFunctor;
|
||||
child->m_root = isRoot() ? this : m_root;
|
||||
|
||||
// immmediate offspring of the root branch needs not copy anything. For the rest,
|
||||
// deep-copy joints, overridden item map and pointers to stored items.
|
||||
// immmediate offspring of the root branch needs not copy anything.
|
||||
// For the rest, deep-copy joints, overridden item map and pointers
|
||||
// to stored items.
|
||||
if( !isRoot() )
|
||||
{
|
||||
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_joints = m_joints;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::unlinkParent()
|
||||
{
|
||||
if( isRoot() )
|
||||
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 )
|
||||
{
|
||||
|
@ -141,27 +150,34 @@ void PNS_NODE::unlinkParent ( )
|
|||
}
|
||||
|
||||
|
||||
// function object that visits potential obstacles and performs the actual collision refining
|
||||
struct PNS_NODE::obstacleVisitor {
|
||||
// function object that visits potential obstacles and performs
|
||||
// the actual collision refining
|
||||
struct PNS_NODE::obstacleVisitor
|
||||
{
|
||||
///> node we are searching in (either root or a branch)
|
||||
PNS_NODE* m_node;
|
||||
|
||||
///> node that overrides root entries
|
||||
PNS_NODE* m_override;
|
||||
|
||||
///> list of encountered obstacles
|
||||
Obstacles& m_tab;
|
||||
|
||||
///> the item we are looking for collisions with
|
||||
const PNS_ITEM* m_item;
|
||||
|
||||
///> acccepted kinds of colliding items (solids, vias, segments, etc...)
|
||||
int m_kindMask;
|
||||
|
||||
///> max number of hits
|
||||
int m_limitCount;
|
||||
|
||||
///> number of items found so far
|
||||
int m_matchCount;
|
||||
|
||||
obstacleVisitor( PNS_NODE::Obstacles& aTab,
|
||||
const PNS_ITEM* aItem,
|
||||
int aKindMask )
|
||||
: m_tab(aTab),
|
||||
obstacleVisitor( PNS_NODE::Obstacles& aTab, const PNS_ITEM* aItem,
|
||||
int aKindMask ) :
|
||||
m_tab( aTab ),
|
||||
m_item( aItem ),
|
||||
m_kindMask( aKindMask ),
|
||||
m_limitCount( -1 ),
|
||||
|
@ -183,11 +199,14 @@ struct PNS_NODE::obstacleVisitor {
|
|||
{
|
||||
if( !aItem->OfKind( m_kindMask ) )
|
||||
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 ) )
|
||||
return true;
|
||||
|
||||
int clearance = m_node->GetClearance( aItem, m_item );
|
||||
|
||||
if( !aItem->Collide( m_item, clearance ) )
|
||||
return true;
|
||||
|
||||
|
@ -200,11 +219,14 @@ struct PNS_NODE::obstacleVisitor {
|
|||
|
||||
if( m_limitCount > 0 && m_matchCount >= m_limitCount )
|
||||
return false;
|
||||
|
||||
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 );
|
||||
|
||||
|
@ -226,6 +248,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem, PNS_NODE::Obstacles& aObsta
|
|||
return aObstacles.size();
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask )
|
||||
{
|
||||
Obstacles obs_list;
|
||||
|
@ -236,6 +259,7 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
|
|||
obs_list.reserve( 100 );
|
||||
|
||||
int n = 0;
|
||||
|
||||
for( int i = 0; i < line.SegmentCount(); 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 )
|
||||
{
|
||||
|
||||
int dist = aLine.GetCLine().Length() + (isect.p - aLine.GetVia().GetPos()).EuclideanNorm();
|
||||
int dist = aLine.GetCLine().Length() +
|
||||
( isect.p - aLine.GetVia().GetPos() ).EuclideanNorm();
|
||||
|
||||
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 )
|
||||
{
|
||||
|
||||
int dist = aLine.GetCLine().PathLength( isect.p );
|
||||
|
||||
if( dist < nearest.dist_first )
|
||||
|
@ -319,7 +342,6 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE *aItem, int aKin
|
|||
dist_max = dist;
|
||||
ip_last = isect.p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask )
|
||||
{
|
||||
Obstacles obs;
|
||||
|
||||
obs.reserve( 100 );
|
||||
|
||||
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 ) );
|
||||
n += QueryColliding( &s, obs, aKindMask, 1 );
|
||||
|
||||
if( n )
|
||||
return OptObstacle( obs[0] );
|
||||
}
|
||||
|
@ -351,15 +376,18 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM *aItemA, int aKin
|
|||
if( line->EndsWithVia() )
|
||||
{
|
||||
n += QueryColliding( &line->GetVia(), obs, aKindMask, 1 );
|
||||
|
||||
if( n )
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, int aKindMask )
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
|
||||
struct hitVisitor {
|
||||
|
||||
struct hitVisitor
|
||||
{
|
||||
PNS_ITEMSET& m_items;
|
||||
const VECTOR2I& m_point;
|
||||
PNS_NODE* m_world;
|
||||
|
||||
hitVisitor( PNS_ITEMSET& aTab,
|
||||
const VECTOR2I& aPoint,
|
||||
PNS_NODE *aWorld )
|
||||
: m_items(aTab), m_point(aPoint), m_world(aWorld) { };
|
||||
hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, 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 );
|
||||
|
||||
int cl = 0;
|
||||
|
||||
if( aItem->GetKind() == PNS_ITEM::SEGMENT )
|
||||
cl += static_cast<PNS_SEGMENT*>(aItem)->GetWidth() / 2;
|
||||
|
||||
if( aItem->GetShape()->Collide( &cp, cl ) )
|
||||
m_items.Add( aItem );
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint )
|
||||
{
|
||||
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 );
|
||||
|
||||
m_index->Query( &s, m_maxClearance, visitor );
|
||||
|
@ -417,18 +450,21 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint )
|
|||
return items;
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::addSolid( PNS_SOLID* aSolid )
|
||||
{
|
||||
linkJoint( aSolid->GetCenter(), aSolid->GetLayers(), aSolid->GetNet(), aSolid );
|
||||
m_index->Add( aSolid );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::addVia( PNS_VIA* aVia )
|
||||
{
|
||||
linkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia );
|
||||
m_index->Add( aVia );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::addLine( PNS_LINE* aLine )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
if( aSeg->GetSeg().a == aSeg->GetSeg().b )
|
||||
|
@ -469,9 +506,9 @@ void PNS_NODE::addSegment( PNS_SEGMENT *aSeg )
|
|||
m_index->Add( aSeg );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::Add( PNS_ITEM* aItem )
|
||||
{
|
||||
|
||||
aItem->SetOwner( this );
|
||||
|
||||
switch( aItem->GetKind() )
|
||||
|
@ -500,11 +537,13 @@ void PNS_NODE::Add(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() )
|
||||
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() )
|
||||
m_index->Remove( aItem );
|
||||
|
||||
|
@ -513,6 +552,7 @@ void PNS_NODE::doRemove ( PNS_ITEM *aItem )
|
|||
aItem->SetOwner( NULL );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::removeSegment( PNS_SEGMENT* aSeg )
|
||||
{
|
||||
unlinkJoint( aSeg->GetSeg().a, aSeg->GetLayers(), aSeg->GetNet(), aSeg );
|
||||
|
@ -521,6 +561,7 @@ void PNS_NODE::removeSegment (PNS_SEGMENT *aSeg )
|
|||
doRemove( aSeg );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::removeLine( PNS_LINE* aLine )
|
||||
{
|
||||
vector<PNS_SEGMENT*>* segRefs = aLine->GetLinkedSegments();
|
||||
|
@ -538,6 +579,7 @@ void PNS_NODE::removeLine( PNS_LINE *aLine )
|
|||
aLine->SetOwner( NULL );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::removeVia( PNS_VIA* aVia )
|
||||
{
|
||||
unlinkJoint( aVia->GetPos(), aVia->GetLayers(), aVia->GetNet(), aVia );
|
||||
|
@ -545,26 +587,30 @@ void PNS_NODE::removeVia ( PNS_VIA *aVia )
|
|||
doRemove( aVia );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
|
||||
{
|
||||
Remove( aOldItem );
|
||||
Add( aNewItem );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::Remove( PNS_ITEM* aItem )
|
||||
{
|
||||
|
||||
switch( aItem->GetKind() )
|
||||
{
|
||||
case PNS_ITEM::SOLID:
|
||||
assert( false );
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
removeSegment( static_cast<PNS_SEGMENT*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PNS_ITEM::LINE:
|
||||
removeLine( static_cast<PNS_LINE*>( aItem ) );
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
removeVia( static_cast<PNS_VIA*>( aItem ) );
|
||||
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;
|
||||
|
||||
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() );
|
||||
|
||||
assert( jt );
|
||||
|
@ -595,10 +644,12 @@ void PNS_NODE::followLine(PNS_SEGMENT *current, bool scanDirection, int& pos, in
|
|||
break;
|
||||
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
|
||||
for( int i = i_start + 1; i < i_end; 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 );
|
||||
|
||||
if( segs[i - 1] != 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;
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b )
|
||||
{
|
||||
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;
|
||||
FindLineEnds( line, j_start, j_end );
|
||||
|
||||
if( (j_start == a && j_end == b )|| (j_end == a && j_start == b) )
|
||||
aLines.push_back( line );
|
||||
else
|
||||
delete line;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const PNS_NODE::OptJoint PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
|
||||
{
|
||||
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 ) )
|
||||
return f->second;
|
||||
|
||||
++f;
|
||||
}
|
||||
|
||||
return OptJoint();
|
||||
}
|
||||
|
||||
|
||||
PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
range = m_root->m_joints.equal_range( tag );
|
||||
|
||||
for( f = range.first; f != range.second; ++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;
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
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
|
||||
PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet );
|
||||
|
||||
jt.Unlink( aWhere );
|
||||
}
|
||||
|
||||
|
@ -780,13 +850,15 @@ void PNS_NODE::Dump(bool aLong)
|
|||
all_segs.insert( static_cast<PNS_SEGMENT*>(*i) );
|
||||
}
|
||||
|
||||
|
||||
JointMap::iterator j;
|
||||
|
||||
if( aLong )
|
||||
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;
|
||||
|
||||
for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
|
||||
{
|
||||
const PNS_ITEM* item = *k;
|
||||
|
@ -796,16 +868,21 @@ void PNS_NODE::Dump(bool aLong)
|
|||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int lines_count = 0;
|
||||
|
||||
while( !all_segs.empty() )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
printf( "%s ", (*j)->GetSeg().a.Format().c_str() );
|
||||
|
||||
if( j + 1 == seg_refs->end() )
|
||||
printf( "%s\n", (*j)->GetSeg().b.Format().c_str() );
|
||||
|
||||
all_segs.erase( *j );
|
||||
}
|
||||
|
||||
lines_count++;
|
||||
}
|
||||
|
||||
|
@ -831,6 +911,7 @@ void PNS_NODE::Dump(bool aLong)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded )
|
||||
{
|
||||
aRemoved.reserve( m_override.size() );
|
||||
|
@ -846,33 +927,35 @@ void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded)
|
|||
aAdded.push_back( *i );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::releaseChildren()
|
||||
{
|
||||
// copy the kids as the PNS_NODE destructor erases the item from the parent node.
|
||||
vector<PNS_NODE*> kids = m_children;
|
||||
|
||||
BOOST_FOREACH(PNS_NODE *node, kids)
|
||||
{
|
||||
BOOST_FOREACH( PNS_NODE * node, kids ) {
|
||||
node->releaseChildren();
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::Commit( PNS_NODE* aNode )
|
||||
{
|
||||
|
||||
if( aNode->isRoot() )
|
||||
return;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, aNode->m_override )
|
||||
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 );
|
||||
|
||||
releaseChildren();
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::KillChildren()
|
||||
{
|
||||
assert( isRoot() );
|
||||
|
@ -881,7 +964,6 @@ void PNS_NODE::KillChildren()
|
|||
}
|
||||
|
||||
|
||||
|
||||
void PNS_NODE::AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems )
|
||||
{
|
||||
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;
|
||||
|
||||
std::copy( aItems.begin(), l_cur->begin(), l_cur->end() );
|
||||
|
||||
if( !isRoot() )
|
||||
{
|
||||
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 )
|
||||
if( !overrides( *i ) )
|
||||
aItems.push_back( *i );
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ class PNS_INDEX;
|
|||
|
||||
using boost::shared_ptr;
|
||||
|
||||
class PNS_CLEARANCE_FUNC {
|
||||
class PNS_CLEARANCE_FUNC
|
||||
{
|
||||
public:
|
||||
virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0;
|
||||
};
|
||||
|
@ -67,8 +68,8 @@ struct PNS_OBSTACLE
|
|||
///> Hull of the colliding item
|
||||
SHAPE_LINE_CHAIN hull;
|
||||
|
||||
///> First and last intersection point between the head item and the hull of the
|
||||
//// colliding item
|
||||
///> First and last intersection point between the head item and the hull
|
||||
///> of the colliding item
|
||||
VECTOR2I ip_first, ip_last;
|
||||
|
||||
///> ... and the distance thereof
|
||||
|
@ -78,18 +79,19 @@ struct PNS_OBSTACLE
|
|||
/**
|
||||
* 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:
|
||||
* - spatial-indexed container for PCB item shapes
|
||||
* - collision search (with clearance checking)
|
||||
* - 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:
|
||||
|
||||
typedef boost::optional<PNS_OBSTACLE> OptObstacle;
|
||||
typedef std::vector<PNS_ITEM*> ItemVector;
|
||||
typedef std::vector<PNS_OBSTACLE> Obstacles;
|
||||
|
@ -117,17 +119,24 @@ public:
|
|||
m_clearanceFunctor = aFunc;
|
||||
}
|
||||
|
||||
///> Finds items that collide with aItem and stores collision information in aObstacles.
|
||||
int QueryColliding( const PNS_ITEM* aItem, Obstacles& aObstacles, int aKindMask = PNS_ITEM::ANY, int aLimitCount = -1);
|
||||
///> Finds items that collide with aItem and stores collision information
|
||||
///> 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.
|
||||
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 );
|
||||
|
||||
///> 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
|
||||
const PNS_ITEMSET HitTest( const VECTOR2I& aPoint );
|
||||
|
@ -136,12 +145,14 @@ public:
|
|||
void Remove( PNS_ITEM* aItem );
|
||||
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
|
||||
|
||||
///> Creates a lightweight copy ("branch") of self. Note that if there are any branches
|
||||
/// in use, their parents must NOT be deleted.
|
||||
///> Creates a lightweight copy ("branch") of self. Note that if there are
|
||||
///> any branches in use, their parents must NOT be deleted.
|
||||
PNS_NODE* Branch();
|
||||
|
||||
///> Assembles a line connecting two non-trivial joints the segment aSeg belongs to.
|
||||
PNS_LINE *AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint());
|
||||
///> Assembles a line connecting two non-trivial joints the
|
||||
///> segment aSeg belongs to.
|
||||
PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg,
|
||||
const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() );
|
||||
|
||||
///> Dumps the contents and joints structure
|
||||
void Dump( bool aLong = false );
|
||||
|
@ -152,8 +163,8 @@ public:
|
|||
return m_joints.size();
|
||||
}
|
||||
|
||||
///> Returns the lists of items removed and added in this branch, with respect
|
||||
///> to the root.
|
||||
///> Returns the lists of items removed and added in this branch, with
|
||||
///> respect to the root.
|
||||
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded );
|
||||
|
||||
///> 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 );
|
||||
|
||||
///> 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
|
||||
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.
|
||||
void FindConnectedJoints( const PNS_JOINT& aJoint, std::vector<PNS_JOINT *> &aConnectedJoints );
|
||||
///> finds all joints that have an (in)direct connection(s)
|
||||
///> (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.
|
||||
void KillChildren();
|
||||
|
@ -178,7 +192,6 @@ public:
|
|||
void AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems );
|
||||
|
||||
private:
|
||||
|
||||
struct obstacleVisitor;
|
||||
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap;
|
||||
typedef JointMap::value_type TagJointPair;
|
||||
|
@ -188,16 +201,18 @@ private:
|
|||
PNS_NODE& operator=( const PNS_NODE& b );
|
||||
|
||||
///> 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
|
||||
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
|
||||
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
|
||||
|
||||
void addSolid( PNS_SOLID* aSeg );
|
||||
void addSegment( PNS_SEGMENT* aSeg );
|
||||
void addLine( PNS_LINE* aLine );
|
||||
|
@ -216,20 +231,26 @@ private:
|
|||
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
|
||||
{
|
||||
return m_override.find( aItem ) != m_override.end();
|
||||
}
|
||||
|
||||
///> 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
|
||||
// SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
|
||||
|
||||
///> hash table with the joints, linking the items. Joints are hashed by their
|
||||
///> position, layer set and net.
|
||||
///> hash table with the joints, linking the items. Joints are hashed by
|
||||
///> their position, layer set and net.
|
||||
JointMap m_joints;
|
||||
|
||||
///> node this node was branched from
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.or/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <geometry/shape_line_chain.h>
|
||||
|
@ -27,13 +28,12 @@
|
|||
#include "pns_optimizer.h"
|
||||
#include "pns_utils.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
|
||||
Cost Estimator Methods
|
||||
|
||||
*
|
||||
* Cost Estimator Methods
|
||||
*
|
||||
**/
|
||||
|
||||
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:
|
||||
return 1;
|
||||
|
||||
case DIRECTION_45::ANG_STRAIGHT:
|
||||
return 0;
|
||||
|
||||
case DIRECTION_45::ANG_ACUTE:
|
||||
return 50;
|
||||
|
||||
case DIRECTION_45::ANG_RIGHT:
|
||||
return 30;
|
||||
|
||||
case DIRECTION_45::ANG_HALF_FULL:
|
||||
return 60;
|
||||
|
||||
default:
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PNS_COST_ESTIMATOR::CornerCost( const SHAPE_LINE_CHAIN& aLine )
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
for( int i = 0; i < aLine.SegmentCount() - 1; ++i )
|
||||
total += CornerCost( aLine.CSegment( i ), aLine.CSegment( i + 1 ) );
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
|
@ -71,18 +79,21 @@ int PNS_COST_ESTIMATOR::CornerCost ( const PNS_LINE& aLine )
|
|||
return CornerCost( aLine.GetCLine() );
|
||||
}
|
||||
|
||||
|
||||
void PNS_COST_ESTIMATOR::Add( PNS_LINE& aLine )
|
||||
{
|
||||
m_lengthCost += aLine.GetCLine().Length();
|
||||
m_cornerCost += CornerCost( aLine );
|
||||
}
|
||||
|
||||
|
||||
void PNS_COST_ESTIMATOR::Remove( PNS_LINE& aLine )
|
||||
{
|
||||
m_lengthCost -= aLine.GetCLine().Length();
|
||||
m_cornerCost -= CornerCost( aLine );
|
||||
}
|
||||
|
||||
|
||||
void PNS_COST_ESTIMATOR::Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine )
|
||||
{
|
||||
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 )
|
||||
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 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 ) :
|
||||
m_world( aWorld ), m_collisionKindMask( PNS_ITEM::ANY ), m_effortLevel( MERGE_SEGMENTS )
|
||||
{
|
||||
|
@ -125,7 +138,6 @@ PNS_OPTIMIZER::~PNS_OPTIMIZER ( )
|
|||
|
||||
struct PNS_OPTIMIZER::CacheVisitor
|
||||
{
|
||||
|
||||
CacheVisitor( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) :
|
||||
m_ourItem( aOurItem ),
|
||||
m_collidingItem( NULL ),
|
||||
|
@ -153,6 +165,7 @@ struct PNS_OPTIMIZER::CacheVisitor
|
|||
int m_mask;
|
||||
};
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex )
|
||||
{
|
||||
std::vector<PNS_SEGMENT*>* segs = aLine->GetLinkedSegments();
|
||||
|
@ -181,17 +195,20 @@ void PNS_OPTIMIZER::removeCachedSegments (PNS_LINE *aLine, int aStartVertex, int
|
|||
} // *cacheRemove( (*segs)[i] );
|
||||
}
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem )
|
||||
{
|
||||
if( aItem->GetKind() == PNS_ITEM::LINE )
|
||||
removeCachedSegments( static_cast<PNS_LINE*> (aItem) );
|
||||
}
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::CacheStaticItem( PNS_ITEM* aItem )
|
||||
{
|
||||
cacheAdd( aItem, true );
|
||||
}
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
|
||||
{
|
||||
if( !aStaticOnly )
|
||||
|
@ -211,6 +228,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache )
|
||||
{
|
||||
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 );
|
||||
|
||||
if(obs) {
|
||||
|
||||
if( obs )
|
||||
{
|
||||
if( aUpdateCache )
|
||||
cacheAdd( obs->item );
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cacheTags[v.m_collidingItem].hits++;
|
||||
return true;
|
||||
}
|
||||
|
@ -238,12 +259,15 @@ bool PNS_OPTIMIZER::checkColliding ( PNS_ITEM *aItem, bool aUpdateCache )
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath )
|
||||
{
|
||||
PNS_LINE tmp( *aLine, aOptPath );
|
||||
|
||||
return checkColliding( &tmp );
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::mergeObtuse( PNS_LINE* aLine )
|
||||
{
|
||||
SHAPE_LINE_CHAIN& line = aLine->GetLine();
|
||||
|
@ -262,6 +286,7 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
|
|||
iter++;
|
||||
int n_segs = current_path.SegmentCount();
|
||||
int max_step = n_segs - 2;
|
||||
|
||||
if( step > max_step )
|
||||
step = max_step;
|
||||
|
||||
|
@ -288,7 +313,9 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
|
|||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
s1opt = SEG( s1.a, ip );
|
||||
s2opt = SEG( ip, s2.b );
|
||||
}
|
||||
|
@ -313,6 +340,7 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -323,9 +351,11 @@ bool PNS_OPTIMIZER::mergeObtuse (PNS_LINE *aLine)
|
|||
line = current_path;
|
||||
return line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
step--;
|
||||
}
|
||||
}
|
||||
|
||||
return line.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
|
@ -359,8 +389,6 @@ bool PNS_OPTIMIZER::mergeFull(PNS_LINE *aLine)
|
|||
|
||||
if( !found_anything )
|
||||
step--;
|
||||
|
||||
|
||||
}
|
||||
|
||||
aLine->SetShape( current_path );
|
||||
|
@ -368,6 +396,7 @@ bool PNS_OPTIMIZER::mergeFull(PNS_LINE *aLine)
|
|||
return current_path.SegmentCount() < segs_pre;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, PNS_LINE* aResult, int aStartVertex, int aEndVertex )
|
||||
{
|
||||
if( !aResult )
|
||||
|
@ -378,10 +407,13 @@ bool PNS_OPTIMIZER::Optimize ( PNS_LINE *aLine, PNS_LINE *aResult , int aStartVe
|
|||
m_keepPostures = false;
|
||||
|
||||
bool rv = false;
|
||||
|
||||
if( m_effortLevel & MERGE_SEGMENTS )
|
||||
rv |= mergeFull( aResult );
|
||||
|
||||
if( m_effortLevel & MERGE_OBTUSE )
|
||||
rv |= mergeObtuse( aResult );
|
||||
|
||||
if( m_effortLevel & SMART_PADS )
|
||||
rv |= runSmartPads( aResult );
|
||||
|
||||
|
@ -443,13 +475,16 @@ bool PNS_OPTIMIZER::mergeStep ( PNS_LINE *aLine, SHAPE_LINE_CHAIN& aCurrentPath,
|
|||
aCurrentPath = *picked;
|
||||
return true;
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -463,11 +498,13 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth, const SH
|
|||
l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) );
|
||||
breakouts.push_back( l );
|
||||
}
|
||||
|
||||
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);
|
||||
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 )
|
||||
{
|
||||
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)));
|
||||
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 {
|
||||
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 ) ) );
|
||||
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
|
||||
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)));
|
||||
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)));
|
||||
|
||||
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 ) ) );
|
||||
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, const PNS_ITEM *aItem, bool aPermitDiagonal ) const
|
||||
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth,
|
||||
const PNS_ITEM* aItem, bool aPermitDiagonal ) const
|
||||
{
|
||||
switch( aItem->GetKind() )
|
||||
{
|
||||
|
@ -526,25 +572,32 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth, const P
|
|||
case PNS_ITEM::SOLID:
|
||||
{
|
||||
const SHAPE* shape = aItem->GetShape();
|
||||
|
||||
switch( shape->Type() )
|
||||
{
|
||||
case SH_RECT:
|
||||
return rectBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
case SH_CIRCLE:
|
||||
return circleBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BreakoutList();
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const
|
||||
{
|
||||
PNS_NODE::OptJoint jt = m_world->FindJoint( aP, aLayer, aNet );
|
||||
|
||||
if( !jt )
|
||||
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 )
|
||||
return item;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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_len = INT_MAX;
|
||||
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;
|
||||
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++ )
|
||||
{
|
||||
BOOST_FOREACH(SHAPE_LINE_CHAIN& l, breakouts)
|
||||
{
|
||||
BOOST_FOREACH( SHAPE_LINE_CHAIN & l, breakouts ) {
|
||||
// PNSDisplayDebugLine (l, 0);
|
||||
|
||||
|
||||
for( int diag = 0; diag < 2; diag++ )
|
||||
{
|
||||
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_head ( line.CSegment(p + 1));
|
||||
|
@ -619,7 +675,6 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
|
|||
vp.second.Simplify();
|
||||
variants.push_back( vp );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -636,12 +691,10 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd,
|
|||
|
||||
if( !checkColliding( &tmp ) )
|
||||
{
|
||||
|
||||
|
||||
/* if(aEnd)
|
||||
PNSDisplayDebugLine (l_best, 6);
|
||||
else
|
||||
PNSDisplayDebugLine (l_best, 5);*/
|
||||
* PNSDisplayDebugLine (l_best, 6);
|
||||
* else
|
||||
* PNSDisplayDebugLine (l_best, 5);*/
|
||||
|
||||
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 )
|
||||
min_len = std::min( len, min_len );
|
||||
|
||||
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 );
|
||||
return p_best;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine )
|
||||
{
|
||||
SHAPE_LINE_CHAIN& line = aLine->GetLine();
|
||||
|
@ -688,17 +743,22 @@ bool PNS_OPTIMIZER::runSmartPads(PNS_LINE *aLine)
|
|||
|
||||
if( startPad )
|
||||
vtx = smartPadsSingle( aLine, startPad, false, 3 );
|
||||
|
||||
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();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld )
|
||||
{
|
||||
PNS_OPTIMIZER opt( aWorld ? aWorld : aLine->GetWorld() );
|
||||
|
||||
opt.SetEffortLevel( aEffortLevel );
|
||||
opt.SetCollisionMask( -1 );
|
||||
return opt.Optimize( aLine );
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.or/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PNS_OPTIMIZER_H
|
||||
#define __PNS_OPTIMIZER_H
|
||||
|
||||
|
@ -30,7 +31,6 @@ class PNS_NODE;
|
|||
class PNS_LINE;
|
||||
class PNS_ROUTER;
|
||||
|
||||
|
||||
/**
|
||||
* Class PNS_COST_ESTIMATOR
|
||||
*
|
||||
|
@ -60,7 +60,8 @@ class PNS_COST_ESTIMATOR
|
|||
void Remove( PNS_LINE& aLine );
|
||||
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 GetCornerCost() const { return m_cornerCost; }
|
||||
|
@ -85,11 +86,11 @@ class PNS_COST_ESTIMATOR
|
|||
class PNS_OPTIMIZER
|
||||
{
|
||||
public:
|
||||
|
||||
enum OptimizationEffort {
|
||||
MERGE_SEGMENTS = 0x1,
|
||||
SMART_PADS = 0x2,
|
||||
MERGE_OBTUSE = 0x4
|
||||
enum OptimizationEffort
|
||||
{
|
||||
MERGE_SEGMENTS = 0x01,
|
||||
SMART_PADS = 0x02,
|
||||
MERGE_OBTUSE = 0x04
|
||||
};
|
||||
|
||||
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
|
||||
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 CacheStaticItem( PNS_ITEM* aItem );
|
||||
|
@ -116,7 +118,6 @@ class PNS_OPTIMIZER
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
static const int MaxCachedItems = 256;
|
||||
|
||||
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 rectBreakouts( 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 );
|
||||
|
||||
|
@ -162,3 +164,4 @@ class PNS_OPTIMIZER
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.or/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
|
@ -52,7 +53,8 @@
|
|||
|
||||
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;
|
||||
|
||||
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 );
|
||||
int clearance = nc->GetClearance();
|
||||
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();
|
||||
|
@ -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 net_b = b->GetNet();
|
||||
int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance);
|
||||
|
||||
return std::max( cl_a, cl_b );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vector<int> m_clearanceCache;
|
||||
int m_defaultClearance;
|
||||
};
|
||||
|
@ -99,6 +102,7 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
|
|||
case PAD_STANDARD:
|
||||
layers = PNS_LAYERSET( 0, 15 );
|
||||
break;
|
||||
|
||||
case PAD_SMD:
|
||||
case PAD_CONN:
|
||||
{
|
||||
|
@ -111,8 +115,11 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
|
|||
layers = PNS_LAYERSET( i );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() );
|
||||
return NULL;
|
||||
|
@ -130,7 +137,6 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
|
|||
|
||||
solid->SetCenter( c );
|
||||
|
||||
|
||||
double orient = aPad->GetOrientation() / 10.0;
|
||||
|
||||
if( orient == 90.0 || orient == 270.0 )
|
||||
|
@ -147,6 +153,7 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
|
|||
case PAD_CIRCLE:
|
||||
solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
|
||||
break;
|
||||
|
||||
case PAD_OVAL:
|
||||
if( sz.x == sz.y )
|
||||
solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
|
||||
|
@ -164,15 +171,15 @@ PNS_ITEM *PNS_ROUTER::syncPad( D_PAD *aPad )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
solid->SetParent( aPad );
|
||||
return solid;
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEM* PNS_ROUTER::syncTrack( TRACK* aTrack )
|
||||
{
|
||||
|
||||
PNS_SEGMENT *s = new PNS_SEGMENT( SEG (aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNet() );
|
||||
PNS_SEGMENT* s =
|
||||
new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNet() );
|
||||
|
||||
s->SetWidth( aTrack->GetWidth() );
|
||||
s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) );
|
||||
|
@ -193,12 +200,14 @@ PNS_ITEM *PNS_ROUTER::syncVia( SEGVIA *aVia )
|
|||
return v;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::SetBoard( BOARD* aBoard )
|
||||
{
|
||||
m_board = aBoard;
|
||||
TRACE( 1, "m_board = %p\n", m_board );
|
||||
}
|
||||
|
||||
|
||||
int PNS_ROUTER::NextCopperLayer( bool aUp )
|
||||
{
|
||||
LAYER_MSK mask = m_board->GetEnabledLayers() & m_board->GetVisibleLayers();
|
||||
|
@ -206,6 +215,7 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
|
|||
|
||||
do {
|
||||
l += ( aUp ? 1 : -1 );
|
||||
|
||||
if( l > LAST_COPPER_LAYER )
|
||||
l = FIRST_COPPER_LAYER;
|
||||
|
||||
|
@ -214,12 +224,12 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
|
|||
|
||||
if( mask & GetLayerMask( l ) )
|
||||
return l;
|
||||
|
||||
} while( l != m_currentLayer );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::SyncWorld()
|
||||
{
|
||||
vector<D_PAD*> pads;
|
||||
|
@ -239,9 +249,9 @@ void PNS_ROUTER::SyncWorld()
|
|||
m_world->SetMaxClearance( 1000000 ); // m_board->GetBiggestClearanceValue());
|
||||
pads = m_board->GetPads();
|
||||
|
||||
BOOST_FOREACH( D_PAD *pad, pads )
|
||||
{
|
||||
BOOST_FOREACH( D_PAD * pad, pads ) {
|
||||
PNS_ITEM* solid = syncPad( pad );
|
||||
|
||||
if( solid )
|
||||
m_world->Add( solid );
|
||||
}
|
||||
|
@ -250,6 +260,7 @@ void PNS_ROUTER::SyncWorld()
|
|||
{
|
||||
KICAD_T type = t->Type();
|
||||
PNS_ITEM* item = NULL;
|
||||
|
||||
if( type == PCB_TRACE_T )
|
||||
item = syncTrack( t );
|
||||
else if( type == PCB_VIA_T )
|
||||
|
@ -262,6 +273,7 @@ void PNS_ROUTER::SyncWorld()
|
|||
m_placer = new PNS_LINE_PLACER( m_world );
|
||||
}
|
||||
|
||||
|
||||
PNS_ROUTER::PNS_ROUTER()
|
||||
{
|
||||
theRouter = this;
|
||||
|
@ -295,26 +307,30 @@ void PNS_ROUTER::SetView(KiGfx::VIEW *aView)
|
|||
m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) );
|
||||
m_view->Add( m_previewItems );
|
||||
m_previewItems->ViewSetVisible( true );
|
||||
|
||||
}
|
||||
|
||||
|
||||
PNS_ROUTER* PNS_ROUTER::GetInstance()
|
||||
{
|
||||
return theRouter;
|
||||
}
|
||||
|
||||
|
||||
PNS_ROUTER::~PNS_ROUTER()
|
||||
{
|
||||
ClearWorld();
|
||||
theRouter = NULL;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::ClearWorld()
|
||||
{
|
||||
if( m_world )
|
||||
delete m_world;
|
||||
|
||||
if( m_clearanceFunc )
|
||||
delete m_clearanceFunc;
|
||||
|
||||
if( m_placer )
|
||||
delete m_placer;
|
||||
|
||||
|
@ -323,12 +339,14 @@ void PNS_ROUTER::ClearWorld()
|
|||
m_placer = NULL;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::SetCurrentWidth( int w )
|
||||
{
|
||||
// fixme: change width while routing
|
||||
m_currentWidth = w;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_ROUTER::RoutingInProgress() const
|
||||
{
|
||||
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();
|
||||
aSplitsSegment = false;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
anchor = static_cast<PNS_VIA*>(item)->GetPos();
|
||||
aSplitsSegment = false;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
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;
|
||||
else if( (aP - s.b).EuclideanNorm() < w / 2 )
|
||||
anchor = s.b;
|
||||
else {
|
||||
else
|
||||
{
|
||||
anchor = s.NearestPoint( aP );
|
||||
aSplitsSegment = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return anchor;
|
||||
}
|
||||
|
||||
|
@ -412,21 +436,22 @@ void PNS_ROUTER::StartRouting(const VECTOR2I& aP, PNS_ITEM *aStartItem)
|
|||
m_originalStart = 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_state = ROUTE_TRACK;
|
||||
|
||||
if( splitSeg )
|
||||
splitAdjacentSegments( m_placer->GetCurrentNode(), aStartItem, p );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
const VECTOR2I PNS_ROUTER::GetCurrentEnd() const
|
||||
{
|
||||
return m_currentEnd;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::EraseView()
|
||||
{
|
||||
BOOST_FOREACH( BOARD_ITEM* item, m_hiddenItems )
|
||||
|
@ -436,15 +461,17 @@ void PNS_ROUTER::EraseView()
|
|||
|
||||
if( m_previewItems )
|
||||
m_previewItems->FreeItems();
|
||||
|
||||
m_previewItems->ViewUpdate( KiGfx::VIEW_ITEM::GEOMETRY );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, bool aIsHead )
|
||||
{
|
||||
|
||||
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems );
|
||||
|
||||
m_previewItems->Add( pitem );
|
||||
|
||||
if( aIsHead )
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
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 )
|
||||
return;
|
||||
|
||||
// TODO is something missing here?
|
||||
if( m_state == START_ROUTING )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
EraseView();
|
||||
|
@ -495,8 +523,7 @@ void PNS_ROUTER::Move(const VECTOR2I& aP, PNS_ITEM *endItem)
|
|||
|
||||
m_placer->GetCurrentNode()->GetUpdatedItems( removed, added );
|
||||
|
||||
BOOST_FOREACH(PNS_ITEM *item, added)
|
||||
{
|
||||
BOOST_FOREACH( PNS_ITEM* item, added ) {
|
||||
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 )
|
||||
{
|
||||
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[1]->SetEnds( aP, s_old->GetSeg().b );
|
||||
|
||||
|
||||
aNode->Remove( s_old );
|
||||
aNode->Add( s_new[0] );
|
||||
aNode->Add( s_new[1] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::commitRouting( PNS_NODE* aNode )
|
||||
{
|
||||
PNS_NODE::ItemVector removed, added;
|
||||
|
@ -560,6 +588,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
|
|||
BOOST_FOREACH( PNS_ITEM* item, added )
|
||||
{
|
||||
BOARD_ITEM* newBI = NULL;
|
||||
|
||||
switch( item->GetKind() )
|
||||
{
|
||||
case PNS_ITEM::SEGMENT:
|
||||
|
@ -605,6 +634,7 @@ void PNS_ROUTER::commitRouting( PNS_NODE *aNode )
|
|||
m_world->Commit( aNode );
|
||||
}
|
||||
|
||||
|
||||
PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const
|
||||
{
|
||||
PNS_VIA* theVia = NULL;
|
||||
|
@ -615,22 +645,23 @@ PNS_VIA *PNS_ROUTER::checkLoneVia ( PNS_JOINT* aJoint ) const
|
|||
if( item->GetKind() == PNS_ITEM::VIA )
|
||||
theVia = static_cast<PNS_VIA*>( item );
|
||||
|
||||
|
||||
l.Merge( item->GetLayers() );
|
||||
}
|
||||
|
||||
if( l.Start() == l.End() )
|
||||
return theVia;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE* PNS_ROUTER::removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg )
|
||||
{
|
||||
PNS_LINE* ourLine = aNode->AssembleLine( aLatestSeg );
|
||||
PNS_NODE* cleaned = aNode->Branch();
|
||||
PNS_JOINT a, b;
|
||||
vector<PNS_LINE *> lines;
|
||||
|
||||
vector<PNS_LINE*> lines;
|
||||
|
||||
cleaned->FindLineEnds( ourLine, a, b );
|
||||
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 real_end = false;
|
||||
|
@ -676,6 +706,7 @@ bool PNS_ROUTER::FixRoute(const VECTOR2I& aP, PNS_ITEM *aEndItem)
|
|||
splitAdjacentSegments( latest, aEndItem, aP );
|
||||
|
||||
PNS_SEGMENT* lastSeg = NULL;
|
||||
|
||||
for( int i = 0; i < last; 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_world->KillChildren();
|
||||
} else {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = ROUTE_TRACK;
|
||||
m_placer->SetInitialDirection( d_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_placingVia = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return real_end;
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::StopRouting()
|
||||
{
|
||||
if( !RoutingInProgress() )
|
||||
|
@ -733,18 +764,22 @@ void PNS_ROUTER::StopRouting()
|
|||
m_world->KillChildren();
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::FlipPosture()
|
||||
{
|
||||
if( m_placer->GetTail().GetCLine().SegmentCount() == 0 )
|
||||
{
|
||||
m_start_diagonal = !m_start_diagonal;
|
||||
m_placer->SetInitialDirection(m_start_diagonal ? DIRECTION_45(DIRECTION_45::NE) : DIRECTION_45(DIRECTION_45::N));
|
||||
} else
|
||||
m_placer->SetInitialDirection( m_start_diagonal ? DIRECTION_45(
|
||||
DIRECTION_45::NE ) : DIRECTION_45( DIRECTION_45::N ) );
|
||||
}
|
||||
else
|
||||
m_placer->FlipPosture();
|
||||
|
||||
Move( m_currentEnd, NULL );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::SwitchLayer( int layer )
|
||||
{
|
||||
switch( m_state )
|
||||
|
@ -752,17 +787,21 @@ void PNS_ROUTER::SwitchLayer(int layer)
|
|||
case IDLE:
|
||||
m_currentLayer = layer;
|
||||
break;
|
||||
|
||||
case ROUTE_TRACK:
|
||||
if( m_startsOnVia )
|
||||
{
|
||||
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:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::ToggleViaPlacement()
|
||||
{
|
||||
if( m_state == ROUTE_TRACK )
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.or/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __PNS_ROUTER_H
|
||||
#define __PNS_ROUTER_H
|
||||
|
||||
|
@ -59,10 +60,11 @@ namespace KiGfx {
|
|||
* Main router class.
|
||||
*/
|
||||
|
||||
class PNS_ROUTER {
|
||||
|
||||
class PNS_ROUTER
|
||||
{
|
||||
private:
|
||||
enum RouterState {
|
||||
enum RouterState
|
||||
{
|
||||
IDLE,
|
||||
START_ROUTING,
|
||||
ROUTE_TRACK,
|
||||
|
@ -70,7 +72,6 @@ private:
|
|||
};
|
||||
|
||||
public:
|
||||
|
||||
PNS_ROUTER();
|
||||
~PNS_ROUTER();
|
||||
|
||||
|
@ -106,10 +107,12 @@ public:
|
|||
|
||||
void EraseView();
|
||||
void SwitchLayer( int layer );
|
||||
|
||||
int GetCurrentLayer() const { return m_currentLayer; }
|
||||
void ToggleViaPlacement();
|
||||
|
||||
void SetCurrentWidth( int w );
|
||||
|
||||
void SetCurrentViaDiameter( int d ) { m_currentViaDiameter = d; }
|
||||
void SetCurrentViaDrill( int d ) { m_currentViaDrill = d; }
|
||||
int GetCurrentWidth() const { return m_currentWidth; }
|
||||
|
@ -127,7 +130,6 @@ public:
|
|||
return m_placingVia;
|
||||
}
|
||||
|
||||
|
||||
int NextCopperLayer( bool aUp );
|
||||
|
||||
// typedef boost::optional<hoverItem> optHoverItem;
|
||||
|
@ -135,11 +137,7 @@ public:
|
|||
const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP );
|
||||
const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment );
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
void clearViewFlags();
|
||||
|
||||
// optHoverItem queryHoverItemEx(const VECTOR2I& aP);
|
||||
|
@ -161,7 +159,6 @@ private:
|
|||
|
||||
void highlightCurrent( bool enabled );
|
||||
|
||||
|
||||
int m_currentLayer;
|
||||
int m_currentNet;
|
||||
int m_currentWidth;
|
||||
|
@ -191,7 +188,7 @@ private:
|
|||
PNS_CLEARANCE_FUNC* m_clearanceFunc;
|
||||
|
||||
boost::unordered_set<BOARD_ITEM*> m_hiddenItems;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
#define __PNS_ROUTER_SETTINGS
|
||||
|
||||
///> Routing modes
|
||||
enum PNS_MODE {
|
||||
enum PNS_MODE
|
||||
{
|
||||
RM_Ignore = 0, ///> Ignore collisions
|
||||
RM_Shove, ///> Only shove
|
||||
RM_Walkaround, ///> Only walkaround
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
|
||||
class PNS_NODE;
|
||||
|
||||
class PNS_SEGMENT : public PNS_ITEM {
|
||||
class PNS_SEGMENT : public PNS_ITEM
|
||||
{
|
||||
public:
|
||||
PNS_SEGMENT() :
|
||||
PNS_ITEM( SEGMENT )
|
||||
|
@ -61,7 +62,8 @@ public:
|
|||
|
||||
PNS_SEGMENT* Clone() const;
|
||||
|
||||
const SHAPE* GetShape() const {
|
||||
const SHAPE* GetShape() const
|
||||
{
|
||||
return static_cast<const SHAPE*>( &m_shape );
|
||||
}
|
||||
|
||||
|
@ -85,14 +87,18 @@ public:
|
|||
m_width = aWidth;
|
||||
}
|
||||
|
||||
int GetWidth() const {
|
||||
int GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
const SEG GetSeg() const {
|
||||
const SEG GetSeg() const
|
||||
{
|
||||
assert( 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( 1 ) );
|
||||
}
|
||||
|
||||
|
@ -111,9 +117,9 @@ public:
|
|||
const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const;
|
||||
|
||||
private:
|
||||
|
||||
SHAPE_LINE_CHAIN m_shape;
|
||||
int m_width;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,11 +43,14 @@ PNS_SHOVE::PNS_SHOVE( PNS_NODE *aWorld )
|
|||
m_iterLimit = 100;
|
||||
};
|
||||
|
||||
|
||||
PNS_SHOVE::~PNS_SHOVE()
|
||||
{
|
||||
}
|
||||
|
||||
struct range {
|
||||
|
||||
struct range
|
||||
{
|
||||
range()
|
||||
{
|
||||
min_v = max_v = -1;
|
||||
|
@ -56,6 +59,7 @@ struct range {
|
|||
void add( int x )
|
||||
{
|
||||
if( min_v < 0 ) min_v = x;
|
||||
|
||||
if( max_v < 0 ) max_v = x;
|
||||
|
||||
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.
|
||||
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();
|
||||
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());
|
||||
}
|
||||
|
||||
/*... special case for vias? */
|
||||
|
||||
return !aNode->CheckColliding( aResult, aHead );
|
||||
}
|
||||
|
||||
int ns = head.SegmentCount();
|
||||
|
||||
if( aHead->EndsWithVia() )
|
||||
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 ) );
|
||||
|
||||
|
||||
|
||||
if( aNode->CheckColliding( &hs, aObstacle ) )
|
||||
{
|
||||
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 ) );
|
||||
hull = hs.Hull( clearance, 0 );
|
||||
} else
|
||||
}
|
||||
else
|
||||
hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 );
|
||||
|
||||
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 );
|
||||
|
||||
/*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 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 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());
|
||||
* }*/
|
||||
|
||||
tmp = shoved.GetCLine();
|
||||
|
||||
if( path_walk.SegmentCount() )
|
||||
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( 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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
|
@ -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_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;
|
||||
else if( !sh_shoved.SegmentCount() )
|
||||
return SH_NULL;
|
||||
|
@ -222,6 +232,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCu
|
|||
return SH_INCOMPLETE;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_SHOVE::reduceSpringback( PNS_LINE* aHead )
|
||||
{
|
||||
bool rv = false;
|
||||
|
@ -236,13 +247,15 @@ bool PNS_SHOVE::reduceSpringback( PNS_LINE *aHead )
|
|||
rv = true;
|
||||
delete st_stack.node;
|
||||
m_nodeStack.pop_back();
|
||||
} else
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost )
|
||||
{
|
||||
BOX2I headBB = aHead->GetCLine().BBox();
|
||||
|
@ -255,6 +268,7 @@ bool PNS_SHOVE::pushSpringback( PNS_NODE *aNode, PNS_LINE *aHead, const PNS_COST
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const
|
||||
{
|
||||
if( m_nodeStack.empty() )
|
||||
|
@ -263,6 +277,7 @@ const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const
|
|||
return m_nodeStack.back().cost;
|
||||
}
|
||||
|
||||
|
||||
PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead )
|
||||
{
|
||||
stack <PNS_LINE*> lineStack;
|
||||
|
@ -296,20 +311,20 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
PNS_NODE::OptObstacle nearest;
|
||||
|
||||
optimizer.CacheStaticItem( head );
|
||||
|
||||
if( 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;
|
||||
prof_counter totalRealTime;
|
||||
|
||||
|
||||
wxLongLong t_start = wxGetLocalTimeMillis();
|
||||
|
||||
while( !lineStack.empty() )
|
||||
{
|
||||
|
||||
wxLongLong t_cur = wxGetLocalTimeMillis();
|
||||
|
||||
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 );
|
||||
|
||||
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;
|
||||
prof_start( &totalRealTime, false );
|
||||
|
||||
|
@ -357,14 +373,16 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
if( original->BelongsTo( node ) )
|
||||
delete original;
|
||||
}
|
||||
|
||||
prof_end( &totalRealTime );
|
||||
|
||||
TRACE( 2, "t-optimizeObstacle %lld us", (totalRealTime.value ) );
|
||||
|
||||
}
|
||||
lineStack.pop();
|
||||
} else {
|
||||
|
||||
lineStack.pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( nearest->item->GetKind() )
|
||||
{
|
||||
case PNS_ITEM::SEGMENT:
|
||||
|
@ -376,7 +394,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
PNS_LINE* shovedLine = collidingLine->CloneProperties();
|
||||
|
||||
prof_start( &totalRealTime, false );
|
||||
ShoveStatus st = shoveSingleLine(node, currentLine, collidingLine, *pseg, shovedLine);
|
||||
ShoveStatus st = shoveSingleLine( node, currentLine, collidingLine,
|
||||
*pseg, shovedLine );
|
||||
prof_end( &totalRealTime );
|
||||
|
||||
TRACE( 2, "t-shoveSingle %lld us", (totalRealTime.value ) );
|
||||
|
@ -390,7 +409,8 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
|
||||
optimizer.CacheRemove( collidingLine );
|
||||
lineStack.push( shovedLine );
|
||||
} else
|
||||
}
|
||||
else
|
||||
fail = true;
|
||||
|
||||
// lastWalkSolid = NULL;
|
||||
|
@ -410,10 +430,10 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
}
|
||||
|
||||
/* if(lastWalkSolid == nearest->item)
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
}*/
|
||||
* {
|
||||
* fail = true;
|
||||
* break;
|
||||
* }*/
|
||||
|
||||
PNS_WALKAROUND walkaround( node );
|
||||
PNS_LINE* walkaroundLine = currentLine->CloneProperties();
|
||||
|
@ -439,9 +459,11 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
|
|||
// lastWalkSolid = nearest->item;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
} // switch
|
||||
|
||||
if( fail )
|
||||
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 );
|
||||
|
||||
if( !fail )
|
||||
{
|
||||
pushSpringback( node, aCurrentHead, PNS_COST_ESTIMATOR() );
|
||||
return SH_OK;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
delete node;
|
||||
return SH_INCOMPLETE;
|
||||
}
|
||||
|
|
|
@ -30,13 +30,14 @@ class PNS_LINE;
|
|||
class PNS_NODE;
|
||||
class PNS_ROUTER;
|
||||
|
||||
class PNS_SHOVE {
|
||||
|
||||
class PNS_SHOVE
|
||||
{
|
||||
public:
|
||||
PNS_SHOVE( PNS_NODE* aWorld );
|
||||
~PNS_SHOVE();
|
||||
|
||||
enum ShoveStatus {
|
||||
enum ShoveStatus
|
||||
{
|
||||
SH_OK = 0,
|
||||
SH_NULL,
|
||||
SH_INCOMPLETE
|
||||
|
@ -55,17 +56,19 @@ class PNS_SHOVE {
|
|||
void KillChildNodes();
|
||||
|
||||
private:
|
||||
|
||||
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 pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost );
|
||||
|
||||
struct SpringbackTag {
|
||||
struct SpringbackTag
|
||||
{
|
||||
int64_t length;
|
||||
int segments;
|
||||
VECTOR2I p;
|
||||
|
@ -80,3 +83,4 @@ class PNS_SHOVE {
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -35,21 +35,18 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness)
|
|||
case SH_RECT:
|
||||
{
|
||||
SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape );
|
||||
return OctagonalHull( rect->GetPosition(),
|
||||
rect->GetSize(),
|
||||
aClearance + 1,
|
||||
0.2 * aClearance );
|
||||
return OctagonalHull( rect->GetPosition(), rect->GetSize(),
|
||||
aClearance + 1, 0.2 * aClearance );
|
||||
}
|
||||
|
||||
case SH_CIRCLE:
|
||||
{
|
||||
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
|
||||
int r = circle->GetRadius();
|
||||
return OctagonalHull( circle->GetCenter() - VECTOR2I(r, r),
|
||||
VECTOR2I(2 * r, 2 * r),
|
||||
aClearance + 1,
|
||||
0.52 * (r + aClearance) );
|
||||
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
|
||||
aClearance + 1, 0.52 * (r + aClearance) );
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -57,8 +54,10 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness)
|
|||
return SHAPE_LINE_CHAIN();
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEM* PNS_SOLID::Clone() const
|
||||
{
|
||||
// solids are never cloned as the shove algorithm never moves them
|
||||
assert( false );
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
|
||||
#include "pns_item.h"
|
||||
|
||||
class PNS_SOLID : public PNS_ITEM {
|
||||
class PNS_SOLID : public PNS_ITEM
|
||||
{
|
||||
public:
|
||||
PNS_SOLID() : PNS_ITEM( SOLID )
|
||||
{
|
||||
|
@ -47,6 +48,7 @@ public:
|
|||
{
|
||||
if( m_shape )
|
||||
delete m_shape;
|
||||
|
||||
m_shape = shape;
|
||||
}
|
||||
|
||||
|
@ -61,7 +63,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
VECTOR2I m_center;
|
||||
SHAPE* m_shape;
|
||||
};
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
#include "pns_line.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;
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
#include <math/vector2d.h>
|
||||
#include <geometry/shape_line_chain.h>
|
||||
|
||||
|
||||
/** 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
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force )
|
||||
{
|
||||
|
||||
int mindist = r1 + r2;
|
||||
VECTOR2I delta = p2 - p1;
|
||||
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 )
|
||||
{
|
||||
VECTOR2I vts[] = { VECTOR2I(rp0.x, rp0.y),
|
||||
VECTOR2I vts[] =
|
||||
{
|
||||
VECTOR2I( rp0.x, rp0.y ),
|
||||
VECTOR2I( rp0.x, rp0.y + rsize.y ),
|
||||
VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ),
|
||||
VECTOR2I( rp0.x + rsize.x, rp0.y ),
|
||||
VECTOR2I(rp0.x, rp0.y) };
|
||||
VECTOR2I( rp0.x, rp0.y )
|
||||
};
|
||||
|
||||
int dist = INT_MAX;
|
||||
VECTOR2I nearest;
|
||||
|
@ -56,6 +58,7 @@ static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECT
|
|||
VECTOR2I pn = s.NearestPoint( cc );
|
||||
|
||||
int d = (pn - cc).EuclideanNorm();
|
||||
|
||||
if( d < dist )
|
||||
{
|
||||
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);
|
||||
return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force );
|
||||
}
|
||||
|
||||
case SH_RECT:
|
||||
{
|
||||
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(shape);
|
||||
return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force );
|
||||
}
|
||||
|
||||
default:
|
||||
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;
|
||||
PNS_VIA mv( *this );
|
||||
|
@ -110,7 +119,8 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
|
|||
|
||||
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 )
|
||||
break;
|
||||
|
@ -124,7 +134,8 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
|
|||
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;
|
||||
mv.SetPos( mv.GetPos() + force );
|
||||
|
@ -141,8 +152,10 @@ bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
|
@ -35,7 +35,8 @@ class PNS_VIA : public PNS_ITEM
|
|||
PNS_ITEM( VIA ) {};
|
||||
|
||||
PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) :
|
||||
PNS_ITEM (VIA) {
|
||||
PNS_ITEM( VIA )
|
||||
{
|
||||
SetNet( aNet );
|
||||
SetLayers( aLayers );
|
||||
m_pos = aPos;
|
||||
|
@ -85,7 +86,11 @@ class PNS_VIA : public PNS_ITEM
|
|||
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
|
||||
{
|
||||
|
|
|
@ -42,13 +42,16 @@ void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
|
|||
|
||||
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];
|
||||
|
||||
if( !current_obs )
|
||||
|
@ -64,22 +67,25 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
|
|||
|
||||
if( m_recursiveBlockageCount < 3 )
|
||||
aPath.GetLine().Append( current_obs->hull.NearestPoint( last ) );
|
||||
else {
|
||||
else
|
||||
{
|
||||
aPath = aPath.ClipToNearestObstacle( m_world );
|
||||
return STUCK;
|
||||
}
|
||||
}
|
||||
|
||||
aPath.NewWalkaround(current_obs->hull, path_pre[0], path_walk[0], path_post[0], aWindingDirection);
|
||||
aPath.NewWalkaround(current_obs->hull, path_pre[1], path_walk[1], path_post[1], !aWindingDirection);
|
||||
|
||||
aPath.NewWalkaround( current_obs->hull, path_pre[0], path_walk[0],
|
||||
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_alt = path_walk[1].Length();
|
||||
|
||||
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;
|
||||
|
||||
|
@ -91,7 +97,9 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
|
|||
|
||||
current_obs = nearestObstacle( PNS_LINE( aPath, path_post[1] ) );
|
||||
prev_recursive = false;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pnew = path_pre[0];
|
||||
pnew.Append( path_walk[0] );
|
||||
pnew.Append( path_post[0] );
|
||||
|
@ -102,18 +110,21 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, boo
|
|||
{
|
||||
prev_recursive = false;
|
||||
current_obs = nearestObstacle( PNS_LINE( aPath, path_post[0] ) );
|
||||
} else
|
||||
}
|
||||
else
|
||||
prev_recursive = true;
|
||||
}
|
||||
|
||||
|
||||
pnew.Simplify();
|
||||
aPath.SetShape( pnew );
|
||||
|
||||
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 );
|
||||
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_ccw = path_ccw.GetCLine().Length();
|
||||
|
||||
|
||||
if( m_forceLongerPath )
|
||||
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
|
||||
else
|
||||
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
|
||||
|
||||
break;
|
||||
} else if(s_cw == DONE && !m_forceLongerPath) {
|
||||
}
|
||||
else if( s_cw == DONE && !m_forceLongerPath )
|
||||
{
|
||||
aWalkPath = path_cw;
|
||||
break;
|
||||
} else if (s_ccw == DONE && !m_forceLongerPath) {
|
||||
}
|
||||
else if( s_ccw == DONE && !m_forceLongerPath )
|
||||
{
|
||||
aWalkPath = path_ccw;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
else
|
||||
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
|
||||
|
||||
}
|
||||
|
||||
if( m_cursorApproachMode )
|
||||
|
@ -179,7 +191,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
|
||||
SHAPE_LINE_CHAIN l = aWalkPath.GetCLine();
|
||||
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); 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_n = (nearest - m_cursorPos).SquaredEuclideanNorm();
|
||||
|
||||
|
||||
|
||||
if( dist_n <= dist_a && dist_n < dist_b )
|
||||
{
|
||||
// PNSDisplayDebugLine(l, 3);
|
||||
|
@ -201,6 +210,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( found )
|
||||
{
|
||||
aWalkPath = aInitialPath;
|
||||
|
@ -208,7 +218,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
aWalkPath.SetWorld( m_world );
|
||||
aWalkPath.GetLine().Simplify();
|
||||
|
||||
|
@ -219,3 +228,4 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
|
||||
return st;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,22 +24,22 @@
|
|||
#include "pns_line.h"
|
||||
#include "pns_node.h"
|
||||
|
||||
class PNS_WALKAROUND {
|
||||
|
||||
class PNS_WALKAROUND
|
||||
{
|
||||
static const int DefaultIterationLimit = 50;
|
||||
|
||||
|
||||
|
||||
public:
|
||||
PNS_WALKAROUND( PNS_NODE* aWorld ) :
|
||||
m_world(aWorld), m_iteration_limit(DefaultIterationLimit) {
|
||||
m_world( aWorld ), m_iteration_limit( DefaultIterationLimit )
|
||||
{
|
||||
m_forceSingleDirection = false;
|
||||
m_forceLongerPath = false;
|
||||
m_cursorApproachMode = false;
|
||||
};
|
||||
~PNS_WALKAROUND() {};
|
||||
|
||||
enum WalkaroundStatus {
|
||||
enum WalkaroundStatus
|
||||
{
|
||||
IN_PROGRESS = 0,
|
||||
DONE,
|
||||
STUCK
|
||||
|
@ -60,7 +60,6 @@ class PNS_WALKAROUND {
|
|||
m_solids_only = aSolidsOnly;
|
||||
}
|
||||
|
||||
|
||||
void SetSingleDirection( bool aForceSingleDirection )
|
||||
{
|
||||
m_forceSingleDirection = aForceSingleDirection;
|
||||
|
@ -73,8 +72,8 @@ class PNS_WALKAROUND {
|
|||
m_cursorApproachMode = aEnabled;
|
||||
}
|
||||
|
||||
|
||||
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize = true);
|
||||
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
|
||||
bool aOptimize = true );
|
||||
|
||||
private:
|
||||
void start( const PNS_LINE& aInitialPath );
|
||||
|
|
|
@ -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
|
|
@ -31,25 +31,26 @@
|
|||
|
||||
using namespace KiGfx;
|
||||
|
||||
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM *aItem, VIEW_GROUP *aParent )
|
||||
: EDA_ITEM( NOT_USED )
|
||||
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aParent ) :
|
||||
EDA_ITEM( NOT_USED )
|
||||
{
|
||||
m_Flags = 0;
|
||||
m_parent = aParent;
|
||||
|
||||
if( aItem )
|
||||
Update( aItem );
|
||||
}
|
||||
|
||||
|
||||
ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem )
|
||||
{
|
||||
m_layer = aItem->GetLayers().Start();
|
||||
|
||||
|
||||
m_color = getLayerColor( m_layer );
|
||||
m_color.a = 0.8;
|
||||
|
||||
|
@ -82,12 +83,14 @@ void ROUTER_PREVIEW_ITEM::Update(const PNS_ITEM *aItem)
|
|||
ViewUpdate( GEOMETRY | APPEARANCE );
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::MarkAsHead()
|
||||
{
|
||||
if( m_type != PR_VIA )
|
||||
m_color.Saturate( 1.0 );
|
||||
}
|
||||
|
||||
|
||||
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
||||
{
|
||||
BOX2I bbox;
|
||||
|
@ -98,40 +101,46 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
|||
bbox = m_line.BBox();
|
||||
bbox.Inflate( m_width / 2 );
|
||||
return bbox;
|
||||
|
||||
case PR_VIA:
|
||||
bbox = BOX2I( m_viaCenter, VECTOR2I( 0, 0 ) );
|
||||
bbox.Inflate( m_width / 2 );
|
||||
return bbox;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KiGfx::GAL* aGal ) const
|
||||
{
|
||||
switch( m_type )
|
||||
{
|
||||
case PR_LINE:
|
||||
|
||||
aGal->SetLayerDepth( -100.0 );
|
||||
aGal->SetLineWidth( m_width );
|
||||
aGal->SetStrokeColor( m_color );
|
||||
aGal->SetIsStroke( true );
|
||||
aGal->SetIsFill( false );
|
||||
|
||||
for( int s = 0; s < m_line.SegmentCount(); s++ )
|
||||
aGal->DrawLine( m_line.CSegment( s ).a, m_line.CSegment( s ).b );
|
||||
|
||||
if( m_line.IsClosed() )
|
||||
aGal->DrawLine( m_line.CSegment( -1 ).b, m_line.CSegment( 0 ).a );
|
||||
break;
|
||||
case PR_VIA:
|
||||
|
||||
case PR_VIA:
|
||||
aGal->SetLayerDepth( -101.0 );
|
||||
aGal->SetIsStroke( false );
|
||||
aGal->SetIsFill( true );
|
||||
aGal->SetFillColor( m_color );
|
||||
aGal->DrawCircle( m_viaCenter, m_width / 2 );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -151,6 +160,7 @@ void ROUTER_PREVIEW_ITEM::DebugLine ( const SHAPE_LINE_CHAIN& aLine, int aWidth
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::DebugBox( const BOX2I& aBox, int aStyle )
|
||||
{
|
||||
#if 0
|
||||
|
@ -169,29 +179,52 @@ void ROUTER_PREVIEW_ITEM::DebugBox ( const BOX2I& aBox, int aStyle )
|
|||
#endif
|
||||
}
|
||||
|
||||
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor (int layer ) const
|
||||
|
||||
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
|
||||
{
|
||||
// assert (m_view != NULL);
|
||||
|
||||
PCB_RENDER_SETTINGS *settings = static_cast <PCB_RENDER_SETTINGS*> (m_parent -> GetView() -> GetPainter() -> GetSettings());
|
||||
return settings->GetLayerColor(layer);
|
||||
PCB_RENDER_SETTINGS* settings =
|
||||
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;
|
||||
switch(style)
|
||||
|
||||
switch( aStyle )
|
||||
{
|
||||
case 0: color =COLOR4D(0, 1, 0, 1);break;
|
||||
case 1: color =COLOR4D(1, 0, 0, 0.3);break;
|
||||
case 2: color =COLOR4D(1, 0.5, 0.5, 1);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;
|
||||
case 0:
|
||||
color = COLOR4D( 0, 1, 0, 1 ); break;
|
||||
|
||||
case 1:
|
||||
color = COLOR4D( 1, 0, 0, 0.3 ); break;
|
||||
|
||||
case 2:
|
||||
color = COLOR4D( 1, 0.5, 0.5, 1 ); 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,13 +44,15 @@ class PNS_ROUTER;
|
|||
class ROUTER_PREVIEW_ITEM : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
enum ItemType {
|
||||
enum ItemType
|
||||
{
|
||||
PR_VIA,
|
||||
PR_LINE,
|
||||
PR_STUCK_MARKER
|
||||
};
|
||||
|
||||
enum ItemFlags {
|
||||
enum ItemFlags
|
||||
{
|
||||
PR_SUGGESTION = 1
|
||||
};
|
||||
|
||||
|
@ -62,11 +64,11 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
|
|||
void StuckMarker( VECTOR2I& aPosition );
|
||||
void DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 );
|
||||
void DebugBox( const BOX2I& aBox, int aStyle = 0 );
|
||||
|
||||
void Show( int a, std::ostream& b ) const {};
|
||||
|
||||
const BOX2I ViewBBox() const;
|
||||
|
||||
|
||||
virtual void ViewDraw( int aLayer, KiGfx::GAL* aGal ) const;
|
||||
|
||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const
|
||||
|
@ -78,9 +80,8 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
|
|||
void MarkAsHead();
|
||||
|
||||
private:
|
||||
|
||||
const KiGfx::COLOR4D assignColor ( int style ) const;
|
||||
const KiGfx::COLOR4D getLayerColor (int layer ) const;
|
||||
const KiGfx::COLOR4D assignColor( int aStyle ) const;
|
||||
const KiGfx::COLOR4D getLayerColor( int aLayer ) const;
|
||||
|
||||
KiGfx::VIEW_GROUP* m_parent;
|
||||
|
||||
|
@ -96,8 +97,7 @@ class ROUTER_PREVIEW_ITEM : public EDA_ITEM
|
|||
|
||||
VECTOR2I m_stuckPosition;
|
||||
VECTOR2I m_viaCenter;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -74,7 +74,6 @@ ROUTER_TOOL::~ROUTER_TOOL()
|
|||
|
||||
void ROUTER_TOOL::Reset()
|
||||
{
|
||||
|
||||
if( m_router )
|
||||
delete m_router;
|
||||
|
||||
|
@ -91,14 +90,18 @@ void ROUTER_TOOL::Reset()
|
|||
Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) );
|
||||
}
|
||||
|
||||
|
||||
int ROUTER_TOOL::getDefaultWidth( int aNetCode )
|
||||
{
|
||||
int w, d1, d2;
|
||||
|
||||
getNetclassDimensions( aNetCode, w, d1, d2 );
|
||||
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 );
|
||||
|
||||
|
@ -127,7 +130,8 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
|
|||
if( aLayer > 0 )
|
||||
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 );
|
||||
|
||||
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 )
|
||||
picked_via = item;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if( item->GetLayers().Overlaps( tl ) || !picked_seg )
|
||||
picked_seg = item;
|
||||
}
|
||||
|
@ -163,24 +169,26 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
|
|||
rv = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ROUTER_TOOL::setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage, const wxString& aLowerMessage )
|
||||
void ROUTER_TOOL::setMsgPanel( bool aEnabled, int aEntry,
|
||||
const wxString& aUpperMessage, const wxString& aLowerMessage )
|
||||
{
|
||||
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
|
||||
|
||||
if(m_panelItems.size() <= (unsigned int) entry)
|
||||
m_panelItems.resize(entry + 1);
|
||||
if( m_panelItems.size() <= (unsigned int) aEntry )
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::clearMsgPanel()
|
||||
{
|
||||
PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
|
||||
|
@ -188,18 +196,20 @@ void ROUTER_TOOL::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();
|
||||
|
||||
if(netcode >= 0 && enabled)
|
||||
rs->SetHighlight(true, netcode);
|
||||
if( aNetcode >= 0 && aEnabled )
|
||||
rs->SetHighlight( true, aNetcode );
|
||||
else
|
||||
rs->SetHighlight( false );
|
||||
|
||||
getView()->UpdateAllLayersColor();
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
||||
{
|
||||
VIEW_CONTROLS* ctls = getViewControls();
|
||||
|
@ -211,8 +221,6 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
|||
VECTOR2I p = aEvent.Position();
|
||||
startItem = pickSingleItem( p );
|
||||
|
||||
|
||||
|
||||
if( startItem && startItem->GetNet() >= 0 )
|
||||
{
|
||||
bool dummy;
|
||||
|
@ -220,13 +228,16 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
|||
ctls->ForceCursorPosition( true, cursorPos );
|
||||
|
||||
m_startSnapPoint = cursorPos;
|
||||
|
||||
if( startItem->GetLayers().IsMultilayer() )
|
||||
m_startLayer = tl;
|
||||
else
|
||||
m_startLayer = startItem->GetLayers().Start();
|
||||
|
||||
m_startItem = startItem;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_startItem = NULL;
|
||||
m_startSnapPoint = p;
|
||||
m_startLayer = tl;
|
||||
|
@ -235,6 +246,7 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
|
||||
{
|
||||
VIEW_CONTROLS* ctls = getViewControls();
|
||||
|
@ -263,21 +275,26 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
|
|||
ctls->ForceCursorPosition( true, cursorPos );
|
||||
m_endItem = endItem;
|
||||
m_endSnapPoint = cursorPos;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_endItem = NULL;
|
||||
m_endSnapPoint = p;
|
||||
ctls->ForceCursorPosition( false );
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
VIEW_CONTROLS* ctls = getViewControls();
|
||||
|
||||
int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 );
|
||||
|
||||
if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) )
|
||||
width = static_cast<PNS_SEGMENT*>( m_startItem )->GetWidth();
|
||||
|
||||
|
@ -309,10 +326,13 @@ void ROUTER_TOOL::startRouting ( )
|
|||
else if( evt->IsClick( MB_Left ) )
|
||||
{
|
||||
updateEndItem( *evt );
|
||||
|
||||
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
|
||||
break;
|
||||
|
||||
m_router->Move( m_endSnapPoint, m_endItem );
|
||||
} else if (evt->IsKeyUp())
|
||||
}
|
||||
else if( evt->IsKeyUp() )
|
||||
{
|
||||
switch( evt->KeyCode() )
|
||||
{
|
||||
|
@ -372,7 +392,6 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
// Main loop: keep receiving events
|
||||
while( OPT_TOOL_EVENT evt = Wait() )
|
||||
{
|
||||
|
||||
if( evt->IsCancel() )
|
||||
break; // Finish
|
||||
else if( evt->IsMotion() )
|
||||
|
@ -384,7 +403,6 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// clearMsgPanel();
|
||||
|
||||
// Restore the default settings
|
||||
|
@ -394,4 +412,3 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ private:
|
|||
|
||||
PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
|
||||
|
||||
|
||||
void setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage = wxT(""), const wxString& aLowerMessage = wxT("") );
|
||||
void setMsgPanel( bool enabled, int entry, const wxString& aUpperMessage = wxT(""),
|
||||
const wxString& aLowerMessage = wxT("") );
|
||||
void clearMsgPanel();
|
||||
|
||||
int getDefaultWidth( int aNetCode );
|
||||
|
@ -77,3 +77,4 @@ private:
|
|||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#ifndef __TRACE_H
|
||||
#define __TRACE_H
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define TRACE( level, fmt, ... ) \
|
||||
_trace_print( __FUNCTION__, level, (boost::format( fmt ) % __VA_ARGS__).str() );
|
||||
|
||||
|
|
Loading…
Reference in New Issue