Loading pcbnew/router/CMakeLists.txt +47 −46 Original line number Original line Diff line number Diff line Loading @@ -48,3 +48,4 @@ set(PCBNEW_PNS_SRCS ) ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) pcbnew/router/direction.h +298 −261 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ class DIRECTION_45 class DIRECTION_45 { { public: public: /** /** Loading @@ -39,7 +38,8 @@ public: * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. */ */ enum Directions { enum Directions { N = 0, N = 0, NE = 1, NE = 1, E = 2, E = 2, Loading @@ -55,11 +55,12 @@ public: * Enum AngleType * Enum AngleType * Represents kind of angle formed by vectors heading in two DIRECTION_45s. * Represents kind of angle formed by vectors heading in two DIRECTION_45s. */ */ enum AngleType { enum AngleType ANG_OBTUSE = 0x1, { ANG_RIGHT = 0x2, ANG_OBTUSE = 0x01, ANG_ACUTE = 0x4, ANG_RIGHT = 0x02, ANG_STRAIGHT = 0x8, ANG_ACUTE = 0x04, ANG_STRAIGHT = 0x08, ANG_HALF_FULL = 0x10, ANG_HALF_FULL = 0x10, ANG_UNDEFINED = 0x20 ANG_UNDEFINED = 0x20 }; }; Loading Loading @@ -93,16 +94,35 @@ public: { { switch( m_dir ) switch( m_dir ) { { case N : return "north"; case N: case NE : return "north-east"; return "north"; case E : return "east"; case SE : return "south-east"; case NE: case S : return "south"; return "north-east"; case SW : return "south-west"; case W : return "west"; case E: case NW : return "north-west"; return "east"; case UNDEFINED : return "undefined"; default: return "<Error>"; case SE: return "south-east"; case S: return "south"; case SW: return "south-west"; case W: return "west"; case NW: return "north-west"; case UNDEFINED: return "undefined"; default: return "<Error>"; } } } } Loading @@ -115,6 +135,7 @@ public: { { if( m_dir == UNDEFINED ) if( m_dir == UNDEFINED ) return UNDEFINED; return UNDEFINED; const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE }; const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE }; return OppositeMap[m_dir]; return OppositeMap[m_dir]; } } Loading Loading @@ -172,7 +193,9 @@ public: * @param aStartDiagonal whether the first segment has to be diagonal * @param aStartDiagonal whether the first segment has to be diagonal * @return the trace * @return the trace */ */ const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I& aP0, const VECTOR2I &aP1, bool aStartDiagonal = false) const const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1, bool aStartDiagonal = false ) const { { int w = abs( aP1.x - aP0.x ); int w = abs( aP1.x - aP0.x ); int h = abs( aP1.y - aP0.y ); int h = abs( aP1.y - aP0.y ); Loading @@ -186,7 +209,9 @@ public: { { mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE } else { } else { mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE } } Loading @@ -201,6 +226,7 @@ public: SHAPE_LINE_CHAIN pl; SHAPE_LINE_CHAIN pl; pl.Append( aP0 ); pl.Append( aP0 ); if( start_diagonal ) if( start_diagonal ) pl.Append( aP0 + mp1 ); pl.Append( aP0 + mp1 ); else else Loading @@ -224,15 +250,20 @@ public: const DIRECTION_45 Right() const const DIRECTION_45 Right() const { { DIRECTION_45 r; DIRECTION_45 r; r.m_dir = (Directions) (m_dir + 1); r.m_dir = (Directions) (m_dir + 1); if( r.m_dir == NW ) if( r.m_dir == NW ) r.m_dir = N; r.m_dir = N; return r; return r; } } private: private: template <typename T> int sign(T val) const { template <typename T> int sign( T val ) const { return (T( 0 ) < val) - ( val < T( 0 ) ); return (T( 0 ) < val) - ( val < T( 0 ) ); } } Loading @@ -245,12 +276,15 @@ private: void construct( const VECTOR2I& aVec ) void construct( const VECTOR2I& aVec ) { { m_dir = UNDEFINED; m_dir = UNDEFINED; if( aVec.x == 0 && aVec.y == 0 ) if( aVec.x == 0 && aVec.y == 0 ) return; return; double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0; double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0; if( mag >= 360.0 ) if( mag >= 360.0 ) mag -= 360.0; mag -= 360.0; if( mag < 0.0 ) if( mag < 0.0 ) mag += 360.0; mag += 360.0; Loading @@ -258,10 +292,12 @@ private: if( m_dir >= 8 ) if( m_dir >= 8 ) m_dir = (Directions)( m_dir - 8 ); m_dir = (Directions)( m_dir - 8 ); if( m_dir < 0 ) if( m_dir < 0 ) m_dir = (Directions)( m_dir + 8 ); m_dir = (Directions)( m_dir + 8 ); return; return; if( aVec.y < 0 ) if( aVec.y < 0 ) { { if( aVec.x > 0 ) if( aVec.x > 0 ) Loading Loading @@ -293,3 +329,4 @@ private: }; }; #endif // __DIRECTION_H #endif // __DIRECTION_H pcbnew/router/pns_index.h +181 −159 Original line number Original line Diff line number Diff line Loading @@ -37,10 +37,9 @@ * overlap and improving search time. * overlap and improving search time. **/ **/ class PNS_INDEX { class PNS_INDEX { public: public: typedef std::list<PNS_ITEM*> NetItemsList; typedef std::list<PNS_ITEM*> NetItemsList; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex; typedef boost::unordered_set<PNS_ITEM*> ItemSet; typedef boost::unordered_set<PNS_ITEM*> ItemSet; Loading @@ -54,6 +53,7 @@ public: template<class Visitor> template<class Visitor> int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); template<class Visitor> template<class Visitor> int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); Loading @@ -64,15 +64,14 @@ public: ItemSet::iterator begin() { return m_allItems.begin(); } ItemSet::iterator begin() { return m_allItems.begin(); } ItemSet::iterator end() { return m_allItems.end(); } ItemSet::iterator end() { return m_allItems.end(); } bool Contains ( PNS_ITEM *aItem ) const { bool Contains( PNS_ITEM* aItem ) const { return m_allItems.find( aItem ) != m_allItems.end(); return m_allItems.find( aItem ) != m_allItems.end(); } } int Size() const { return m_allItems.size(); } int Size() const { return m_allItems.size(); } private: private: static const int MaxSubIndices = 64; static const int MaxSubIndices = 64; static const int SI_Multilayer = 2; static const int SI_Multilayer = 2; static const int SI_SegDiagonal = 0; static const int SI_SegDiagonal = 0; Loading @@ -91,11 +90,13 @@ private: ItemSet m_allItems; ItemSet m_allItems; }; }; PNS_INDEX::PNS_INDEX() PNS_INDEX::PNS_INDEX() { { memset( m_subIndices, 0, sizeof( m_subIndices ) ); memset( m_subIndices, 0, sizeof( m_subIndices ) ); } } PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) { { int idx_n = -1; int idx_n = -1; Loading @@ -107,6 +108,7 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) case PNS_ITEM::VIA: case PNS_ITEM::VIA: idx_n = SI_Multilayer; idx_n = SI_Multilayer; break; break; case PNS_ITEM::SOLID: case PNS_ITEM::SOLID: { { if( l.IsMultilayer() ) if( l.IsMultilayer() ) Loading @@ -115,15 +117,19 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) idx_n = SI_PadsTop; idx_n = SI_PadsTop; else if( l.Start() == 15 ) else if( l.Start() == 15 ) idx_n = SI_PadsBottom; idx_n = SI_PadsBottom; break; break; } } case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT: case PNS_ITEM::LINE: case PNS_ITEM::LINE: idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; break; break; default: default: break; break; } } assert( idx_n >= 0 && idx_n < MaxSubIndices ); assert( idx_n >= 0 && idx_n < MaxSubIndices ); if( !m_subIndices[idx_n] ) if( !m_subIndices[idx_n] ) Loading @@ -132,23 +138,26 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) return m_subIndices[idx_n]; return m_subIndices[idx_n]; } } void PNS_INDEX::Add( PNS_ITEM* aItem ) void PNS_INDEX::Add( PNS_ITEM* aItem ) { { ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem ); idx->Add( aItem ); idx->Add( aItem ); m_allItems.insert( aItem ); m_allItems.insert( aItem ); int net = aItem->GetNet(); int net = aItem->GetNet(); if( net >= 0 ) if( net >= 0 ) { { m_netMap[net].push_back( aItem ); m_netMap[net].push_back( aItem ); } } } } void PNS_INDEX::Remove( PNS_ITEM* aItem ) void PNS_INDEX::Remove( PNS_ITEM* aItem ) { { ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem ); idx->Remove( aItem ); idx->Remove( aItem ); m_allItems.erase( aItem ); m_allItems.erase( aItem ); Loading @@ -158,27 +167,30 @@ void PNS_INDEX::Remove( PNS_ITEM *aItem ) m_netMap[net].remove( aItem ); m_netMap[net].remove( aItem ); } } void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) { { Remove( aOldItem ); Remove( aOldItem ); Add( aNewItem ); Add( aNewItem ); } } template<class Visitor> template<class Visitor> int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) { { if( !m_subIndices[index] ) if( !m_subIndices[index] ) return 0; return 0; return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); } } template<class Visitor> template<class Visitor> int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) { { const SHAPE* shape = aItem->GetShape(); const SHAPE* shape = aItem->GetShape(); int total = 0; int total = 0; total += querySingle( SI_Multilayer, shape, aMinDistance, v ); total += querySingle( SI_Multilayer, shape, aMinDistance, v ); const PNS_LAYERSET layers = aItem->GetLayers(); const PNS_LAYERSET layers = aItem->GetLayers(); Loading @@ -188,29 +200,33 @@ template<class Visitor> total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); for( int i = layers.Start(); i <= layers.End(); ++i ) for( int i = layers.Start(); i <= layers.End(); ++i ) total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); } } else { else { int l = layers.Start(); int l = layers.Start(); if( l == 0 ) if( l == 0 ) total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v ); else if( l == 15 ) else if( l == 15 ) total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); } } return total; return total; } } template<class Visitor> template<class Visitor> int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) { { int total = 0; int total = 0; for( int i = 0; i < MaxSubIndices; i++ ) for( int i = 0; i < MaxSubIndices; i++ ) total += querySingle( i, aShape, aMinDistance, v ); total += querySingle( i, aShape, aMinDistance, v ); return total; return total; } } Loading @@ -220,22 +236,28 @@ void PNS_INDEX::Clear() for( int i = 0; i < MaxSubIndices; ++i ) for( int i = 0; i < MaxSubIndices; ++i ) { { ItemShapeIndex* idx = m_subIndices[i]; ItemShapeIndex* idx = m_subIndices[i]; if( idx ) if( idx ) delete idx; delete idx; m_subIndices[i] = NULL; m_subIndices[i] = NULL; } } } } PNS_INDEX::~PNS_INDEX() PNS_INDEX::~PNS_INDEX() { { Clear(); Clear(); } } PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) { { if( m_netMap.find( aNet ) == m_netMap.end() ) if( m_netMap.find( aNet ) == m_netMap.end() ) return NULL; return NULL; return &m_netMap[aNet]; return &m_netMap[aNet]; } } #endif #endif pcbnew/router/pns_item.cpp +53 −36 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,8 @@ #include "pns_item.h" #include "pns_item.h" #include "pns_line.h" #include "pns_line.h" bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const { { // same nets? no collision! // same nets? no collision! if( m_net == aOther->m_net ) if( m_net == aOther->m_net ) Loading @@ -36,7 +37,9 @@ bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNee // fixme: MTV // fixme: MTV } } bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const { { if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) return true; return true; Loading @@ -45,28 +48,42 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V if( aOther->m_kind == LINE ) if( aOther->m_kind == LINE ) { { const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); if( line->EndsWithVia() ) if( line->EndsWithVia() ) return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); } } return false; return false; } } const std::string PNS_ITEM::GetKindStr() const const std::string PNS_ITEM::GetKindStr() const { { switch( m_kind ) switch( m_kind ) { { case LINE: return "line"; case LINE: case SEGMENT: return "segment"; return "line"; case VIA: return "via"; case JOINT: return "joint"; case SEGMENT: case SOLID: return "solid"; return "segment"; default: return "unknown"; case VIA: return "via"; case JOINT: return "joint"; case SOLID: return "solid"; default: return "unknown"; } } } } PNS_ITEM::~PNS_ITEM() PNS_ITEM::~PNS_ITEM() { { } } pcbnew/router/pns_item.h +111 −108 Original line number Original line Diff line number Diff line Loading @@ -41,11 +41,11 @@ class PNS_NODE; class PNS_ITEM class PNS_ITEM { { public: public: static const int UnusedNet = INT_MAX; static const int UnusedNet = INT_MAX; ///> Supported item types ///> Supported item types enum PnsKind { enum PnsKind { SOLID = 1, SOLID = 1, LINE = 2, LINE = 2, JOINT = 4, JOINT = 4, Loading Loading @@ -88,8 +88,6 @@ public: return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN(); }; }; PnsKind GetKind() const { return m_kind; } PnsKind GetKind() const { return m_kind; } bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } Loading @@ -106,7 +104,10 @@ public: ///> Layers accessors ///> Layers accessors const PNS_LAYERSET& GetLayers() const { return m_layers; } const PNS_LAYERSET& GetLayers() const { return m_layers; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); } void SetLayer( int aLayer ) { m_layers = PNS_LAYERSET( aLayer, aLayer ); } ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } Loading @@ -117,29 +118,31 @@ public: void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } PNS_NODE* GetWorld() const { return m_world; } PNS_NODE* GetWorld() const { return m_world; } ///> Collision function. Checks if the item aOther is closer to us than ///> Collision function. Checks if the item aOther is closer to us than /// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the /// aClearance and returns true if so. It can also calculate a minimum translation vector that /// collision if needed. /// resolves the collision if needed. virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; ///> A shortcut without MTV calculation ///> A shortcut without MTV calculation bool Collide( const PNS_ITEM* aOther, int aClearance ) const bool Collide( const PNS_ITEM* aOther, int aClearance ) const { { VECTOR2I dummy; VECTOR2I dummy; return Collide( aOther, aClearance, false, dummy ); return Collide( aOther, aClearance, false, dummy ); } } ///> Returns the geometric shape of the item ///> Returns the geometric shape of the item virtual const SHAPE* GetShape() const { virtual const SHAPE* GetShape() const { return NULL; return NULL; } } private: private: bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; protected: protected: PnsKind m_kind; PnsKind m_kind; BOARD_ITEM* m_parent; BOARD_ITEM* m_parent; Loading @@ -151,5 +154,5 @@ protected: int m_net; int m_net; }; }; #endif // __PNS_ITEM_H #endif // __PNS_ITEM_Ha Loading
pcbnew/router/CMakeLists.txt +47 −46 Original line number Original line Diff line number Diff line Loading @@ -48,3 +48,4 @@ set(PCBNEW_PNS_SRCS ) ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} ) add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
pcbnew/router/direction.h +298 −261 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ class DIRECTION_45 class DIRECTION_45 { { public: public: /** /** Loading @@ -39,7 +38,8 @@ public: * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. */ */ enum Directions { enum Directions { N = 0, N = 0, NE = 1, NE = 1, E = 2, E = 2, Loading @@ -55,11 +55,12 @@ public: * Enum AngleType * Enum AngleType * Represents kind of angle formed by vectors heading in two DIRECTION_45s. * Represents kind of angle formed by vectors heading in two DIRECTION_45s. */ */ enum AngleType { enum AngleType ANG_OBTUSE = 0x1, { ANG_RIGHT = 0x2, ANG_OBTUSE = 0x01, ANG_ACUTE = 0x4, ANG_RIGHT = 0x02, ANG_STRAIGHT = 0x8, ANG_ACUTE = 0x04, ANG_STRAIGHT = 0x08, ANG_HALF_FULL = 0x10, ANG_HALF_FULL = 0x10, ANG_UNDEFINED = 0x20 ANG_UNDEFINED = 0x20 }; }; Loading Loading @@ -93,16 +94,35 @@ public: { { switch( m_dir ) switch( m_dir ) { { case N : return "north"; case N: case NE : return "north-east"; return "north"; case E : return "east"; case SE : return "south-east"; case NE: case S : return "south"; return "north-east"; case SW : return "south-west"; case W : return "west"; case E: case NW : return "north-west"; return "east"; case UNDEFINED : return "undefined"; default: return "<Error>"; case SE: return "south-east"; case S: return "south"; case SW: return "south-west"; case W: return "west"; case NW: return "north-west"; case UNDEFINED: return "undefined"; default: return "<Error>"; } } } } Loading @@ -115,6 +135,7 @@ public: { { if( m_dir == UNDEFINED ) if( m_dir == UNDEFINED ) return UNDEFINED; return UNDEFINED; const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE }; const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE }; return OppositeMap[m_dir]; return OppositeMap[m_dir]; } } Loading Loading @@ -172,7 +193,9 @@ public: * @param aStartDiagonal whether the first segment has to be diagonal * @param aStartDiagonal whether the first segment has to be diagonal * @return the trace * @return the trace */ */ const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I& aP0, const VECTOR2I &aP1, bool aStartDiagonal = false) const const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1, bool aStartDiagonal = false ) const { { int w = abs( aP1.x - aP0.x ); int w = abs( aP1.x - aP0.x ); int h = abs( aP1.y - aP0.y ); int h = abs( aP1.y - aP0.y ); Loading @@ -186,7 +209,9 @@ public: { { mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE } else { } else { mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE } } Loading @@ -201,6 +226,7 @@ public: SHAPE_LINE_CHAIN pl; SHAPE_LINE_CHAIN pl; pl.Append( aP0 ); pl.Append( aP0 ); if( start_diagonal ) if( start_diagonal ) pl.Append( aP0 + mp1 ); pl.Append( aP0 + mp1 ); else else Loading @@ -224,15 +250,20 @@ public: const DIRECTION_45 Right() const const DIRECTION_45 Right() const { { DIRECTION_45 r; DIRECTION_45 r; r.m_dir = (Directions) (m_dir + 1); r.m_dir = (Directions) (m_dir + 1); if( r.m_dir == NW ) if( r.m_dir == NW ) r.m_dir = N; r.m_dir = N; return r; return r; } } private: private: template <typename T> int sign(T val) const { template <typename T> int sign( T val ) const { return (T( 0 ) < val) - ( val < T( 0 ) ); return (T( 0 ) < val) - ( val < T( 0 ) ); } } Loading @@ -245,12 +276,15 @@ private: void construct( const VECTOR2I& aVec ) void construct( const VECTOR2I& aVec ) { { m_dir = UNDEFINED; m_dir = UNDEFINED; if( aVec.x == 0 && aVec.y == 0 ) if( aVec.x == 0 && aVec.y == 0 ) return; return; double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0; double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0; if( mag >= 360.0 ) if( mag >= 360.0 ) mag -= 360.0; mag -= 360.0; if( mag < 0.0 ) if( mag < 0.0 ) mag += 360.0; mag += 360.0; Loading @@ -258,10 +292,12 @@ private: if( m_dir >= 8 ) if( m_dir >= 8 ) m_dir = (Directions)( m_dir - 8 ); m_dir = (Directions)( m_dir - 8 ); if( m_dir < 0 ) if( m_dir < 0 ) m_dir = (Directions)( m_dir + 8 ); m_dir = (Directions)( m_dir + 8 ); return; return; if( aVec.y < 0 ) if( aVec.y < 0 ) { { if( aVec.x > 0 ) if( aVec.x > 0 ) Loading Loading @@ -293,3 +329,4 @@ private: }; }; #endif // __DIRECTION_H #endif // __DIRECTION_H
pcbnew/router/pns_index.h +181 −159 Original line number Original line Diff line number Diff line Loading @@ -37,10 +37,9 @@ * overlap and improving search time. * overlap and improving search time. **/ **/ class PNS_INDEX { class PNS_INDEX { public: public: typedef std::list<PNS_ITEM*> NetItemsList; typedef std::list<PNS_ITEM*> NetItemsList; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex; typedef boost::unordered_set<PNS_ITEM*> ItemSet; typedef boost::unordered_set<PNS_ITEM*> ItemSet; Loading @@ -54,6 +53,7 @@ public: template<class Visitor> template<class Visitor> int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ); template<class Visitor> template<class Visitor> int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); int Query( const SHAPE* aShape, int aMinDistance, Visitor& v ); Loading @@ -64,15 +64,14 @@ public: ItemSet::iterator begin() { return m_allItems.begin(); } ItemSet::iterator begin() { return m_allItems.begin(); } ItemSet::iterator end() { return m_allItems.end(); } ItemSet::iterator end() { return m_allItems.end(); } bool Contains ( PNS_ITEM *aItem ) const { bool Contains( PNS_ITEM* aItem ) const { return m_allItems.find( aItem ) != m_allItems.end(); return m_allItems.find( aItem ) != m_allItems.end(); } } int Size() const { return m_allItems.size(); } int Size() const { return m_allItems.size(); } private: private: static const int MaxSubIndices = 64; static const int MaxSubIndices = 64; static const int SI_Multilayer = 2; static const int SI_Multilayer = 2; static const int SI_SegDiagonal = 0; static const int SI_SegDiagonal = 0; Loading @@ -91,11 +90,13 @@ private: ItemSet m_allItems; ItemSet m_allItems; }; }; PNS_INDEX::PNS_INDEX() PNS_INDEX::PNS_INDEX() { { memset( m_subIndices, 0, sizeof( m_subIndices ) ); memset( m_subIndices, 0, sizeof( m_subIndices ) ); } } PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem ) { { int idx_n = -1; int idx_n = -1; Loading @@ -107,6 +108,7 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) case PNS_ITEM::VIA: case PNS_ITEM::VIA: idx_n = SI_Multilayer; idx_n = SI_Multilayer; break; break; case PNS_ITEM::SOLID: case PNS_ITEM::SOLID: { { if( l.IsMultilayer() ) if( l.IsMultilayer() ) Loading @@ -115,15 +117,19 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) idx_n = SI_PadsTop; idx_n = SI_PadsTop; else if( l.Start() == 15 ) else if( l.Start() == 15 ) idx_n = SI_PadsBottom; idx_n = SI_PadsBottom; break; break; } } case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT: case PNS_ITEM::LINE: case PNS_ITEM::LINE: idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; break; break; default: default: break; break; } } assert( idx_n >= 0 && idx_n < MaxSubIndices ); assert( idx_n >= 0 && idx_n < MaxSubIndices ); if( !m_subIndices[idx_n] ) if( !m_subIndices[idx_n] ) Loading @@ -132,23 +138,26 @@ PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem ) return m_subIndices[idx_n]; return m_subIndices[idx_n]; } } void PNS_INDEX::Add( PNS_ITEM* aItem ) void PNS_INDEX::Add( PNS_ITEM* aItem ) { { ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem ); idx->Add( aItem ); idx->Add( aItem ); m_allItems.insert( aItem ); m_allItems.insert( aItem ); int net = aItem->GetNet(); int net = aItem->GetNet(); if( net >= 0 ) if( net >= 0 ) { { m_netMap[net].push_back( aItem ); m_netMap[net].push_back( aItem ); } } } } void PNS_INDEX::Remove( PNS_ITEM* aItem ) void PNS_INDEX::Remove( PNS_ITEM* aItem ) { { ItemShapeIndex* idx = getSubindex( aItem ); ItemShapeIndex* idx = getSubindex( aItem ); idx->Remove( aItem ); idx->Remove( aItem ); m_allItems.erase( aItem ); m_allItems.erase( aItem ); Loading @@ -158,27 +167,30 @@ void PNS_INDEX::Remove( PNS_ITEM *aItem ) m_netMap[net].remove( aItem ); m_netMap[net].remove( aItem ); } } void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) void PNS_INDEX::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ) { { Remove( aOldItem ); Remove( aOldItem ); Add( aNewItem ); Add( aNewItem ); } } template<class Visitor> template<class Visitor> int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v ) { { if( !m_subIndices[index] ) if( !m_subIndices[index] ) return 0; return 0; return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); return m_subIndices[index]->Query( aShape, aMinDistance, v, false ); } } template<class Visitor> template<class Visitor> int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v ) { { const SHAPE* shape = aItem->GetShape(); const SHAPE* shape = aItem->GetShape(); int total = 0; int total = 0; total += querySingle( SI_Multilayer, shape, aMinDistance, v ); total += querySingle( SI_Multilayer, shape, aMinDistance, v ); const PNS_LAYERSET layers = aItem->GetLayers(); const PNS_LAYERSET layers = aItem->GetLayers(); Loading @@ -188,29 +200,33 @@ template<class Visitor> total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); for( int i = layers.Start(); i <= layers.End(); ++i ) for( int i = layers.Start(); i <= layers.End(); ++i ) total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v ); } } else { else { int l = layers.Start(); int l = layers.Start(); if( l == 0 ) if( l == 0 ) total += querySingle( SI_PadsTop, shape, aMinDistance, v ); total += querySingle( SI_PadsTop, shape, aMinDistance, v ); else if( l == 15 ) else if( l == 15 ) total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_PadsBottom, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v ); } } return total; return total; } } template<class Visitor> template<class Visitor> int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v ) { { int total = 0; int total = 0; for( int i = 0; i < MaxSubIndices; i++ ) for( int i = 0; i < MaxSubIndices; i++ ) total += querySingle( i, aShape, aMinDistance, v ); total += querySingle( i, aShape, aMinDistance, v ); return total; return total; } } Loading @@ -220,22 +236,28 @@ void PNS_INDEX::Clear() for( int i = 0; i < MaxSubIndices; ++i ) for( int i = 0; i < MaxSubIndices; ++i ) { { ItemShapeIndex* idx = m_subIndices[i]; ItemShapeIndex* idx = m_subIndices[i]; if( idx ) if( idx ) delete idx; delete idx; m_subIndices[i] = NULL; m_subIndices[i] = NULL; } } } } PNS_INDEX::~PNS_INDEX() PNS_INDEX::~PNS_INDEX() { { Clear(); Clear(); } } PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet ) { { if( m_netMap.find( aNet ) == m_netMap.end() ) if( m_netMap.find( aNet ) == m_netMap.end() ) return NULL; return NULL; return &m_netMap[aNet]; return &m_netMap[aNet]; } } #endif #endif
pcbnew/router/pns_item.cpp +53 −36 Original line number Original line Diff line number Diff line Loading @@ -21,7 +21,8 @@ #include "pns_item.h" #include "pns_item.h" #include "pns_line.h" #include "pns_line.h" bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const { { // same nets? no collision! // same nets? no collision! if( m_net == aOther->m_net ) if( m_net == aOther->m_net ) Loading @@ -36,7 +37,9 @@ bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNee // fixme: MTV // fixme: MTV } } bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const { { if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) return true; return true; Loading @@ -45,28 +48,42 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V if( aOther->m_kind == LINE ) if( aOther->m_kind == LINE ) { { const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther ); if( line->EndsWithVia() ) if( line->EndsWithVia() ) return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); } } return false; return false; } } const std::string PNS_ITEM::GetKindStr() const const std::string PNS_ITEM::GetKindStr() const { { switch( m_kind ) switch( m_kind ) { { case LINE: return "line"; case LINE: case SEGMENT: return "segment"; return "line"; case VIA: return "via"; case JOINT: return "joint"; case SEGMENT: case SOLID: return "solid"; return "segment"; default: return "unknown"; case VIA: return "via"; case JOINT: return "joint"; case SOLID: return "solid"; default: return "unknown"; } } } } PNS_ITEM::~PNS_ITEM() PNS_ITEM::~PNS_ITEM() { { } }
pcbnew/router/pns_item.h +111 −108 Original line number Original line Diff line number Diff line Loading @@ -41,11 +41,11 @@ class PNS_NODE; class PNS_ITEM class PNS_ITEM { { public: public: static const int UnusedNet = INT_MAX; static const int UnusedNet = INT_MAX; ///> Supported item types ///> Supported item types enum PnsKind { enum PnsKind { SOLID = 1, SOLID = 1, LINE = 2, LINE = 2, JOINT = 4, JOINT = 4, Loading Loading @@ -88,8 +88,6 @@ public: return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN(); }; }; PnsKind GetKind() const { return m_kind; } PnsKind GetKind() const { return m_kind; } bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; } Loading @@ -106,7 +104,10 @@ public: ///> Layers accessors ///> Layers accessors const PNS_LAYERSET& GetLayers() const { return m_layers; } const PNS_LAYERSET& GetLayers() const { return m_layers; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); } void SetLayer( int aLayer ) { m_layers = PNS_LAYERSET( aLayer, aLayer ); } ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; } Loading @@ -117,29 +118,31 @@ public: void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; } PNS_NODE* GetWorld() const { return m_world; } PNS_NODE* GetWorld() const { return m_world; } ///> Collision function. Checks if the item aOther is closer to us than ///> Collision function. Checks if the item aOther is closer to us than /// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the /// aClearance and returns true if so. It can also calculate a minimum translation vector that /// collision if needed. /// resolves the collision if needed. virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; ///> A shortcut without MTV calculation ///> A shortcut without MTV calculation bool Collide( const PNS_ITEM* aOther, int aClearance ) const bool Collide( const PNS_ITEM* aOther, int aClearance ) const { { VECTOR2I dummy; VECTOR2I dummy; return Collide( aOther, aClearance, false, dummy ); return Collide( aOther, aClearance, false, dummy ); } } ///> Returns the geometric shape of the item ///> Returns the geometric shape of the item virtual const SHAPE* GetShape() const { virtual const SHAPE* GetShape() const { return NULL; return NULL; } } private: private: bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; protected: protected: PnsKind m_kind; PnsKind m_kind; BOARD_ITEM* m_parent; BOARD_ITEM* m_parent; Loading @@ -151,5 +154,5 @@ protected: int m_net; int m_net; }; }; #endif // __PNS_ITEM_H #endif // __PNS_ITEM_Ha