Uncrustified the push&shove source, fixed some warnings.

This commit is contained in:
Maciej Suminski 2013-09-27 10:00:26 +02:00
commit 936e0be090
39 changed files with 6254 additions and 5691 deletions

View File

@ -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 );

View File

@ -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;

View File

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

View File

@ -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

View File

@ -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

View File

@ -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()
{
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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] );
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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 );
}
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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

View File

@ -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 )

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 );
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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

View File

@ -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 );
}

View File

@ -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
{

View File

@ -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;
}

View File

@ -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 );

View File

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

View File

@ -31,25 +31,26 @@
using namespace KiGfx;
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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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() );