Commit 5598acb6 authored by Maciej Sumiński's avatar Maciej Sumiński

Uncrustifying push&shove router

parent 87b3f2e4
include_directories(BEFORE ${INC_BEFORE}) include_directories( BEFORE ${INC_BEFORE} )
include_directories( include_directories(
./ ./
../ ../
../../include ../../ include
../../pcbnew ../../ pcbnew
../../polygon ../../ polygon
${INC_AFTER} $ { INC_AFTER }
) )
set(PCBNEW_PNS_SRCS set( PCBNEW_PNS_SRCS
direction.h direction.h
pns_via.h pns_via.h
pns_routing_settings.h pns_routing_settings.h
...@@ -45,6 +45,7 @@ set(PCBNEW_PNS_SRCS ...@@ -45,6 +45,7 @@ set(PCBNEW_PNS_SRCS
router_tool.h router_tool.h
router_preview_item.cpp router_preview_item.cpp
router_preview_item.h router_preview_item.h
) )
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
add_library(pnsrouter STATIC ${PCBNEW_PNS_SRCS})
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
class DIRECTION_45 class DIRECTION_45
{ {
public: public:
/** /**
...@@ -39,7 +38,8 @@ public: ...@@ -39,7 +38,8 @@ public:
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
*/ */
enum Directions { enum Directions
{
N = 0, N = 0,
NE = 1, NE = 1,
E = 2, E = 2,
...@@ -55,31 +55,32 @@ public: ...@@ -55,31 +55,32 @@ 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
}; };
DIRECTION_45(Directions aDir = UNDEFINED): m_dir(aDir) {}; DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {};
/** /**
* Constructor * Constructor
* @param aVec vector, whose direction will be translated into a DIRECTION_45. * @param aVec vector, whose direction will be translated into a DIRECTION_45.
*/ */
DIRECTION_45(const VECTOR2I& aVec) DIRECTION_45( const VECTOR2I& aVec )
{ {
construct(aVec); construct( aVec );
} }
/** /**
* Constructor * Constructor
* @param aSeg segment, whose direction will be translated into a DIRECTION_45. * @param aSeg segment, whose direction will be translated into a DIRECTION_45.
*/ */
DIRECTION_45(const SEG& aSeg) DIRECTION_45( const SEG& aSeg )
{ {
construct( aSeg.b - aSeg.a ); construct( aSeg.b - aSeg.a );
} }
...@@ -91,18 +92,37 @@ public: ...@@ -91,18 +92,37 @@ public:
*/ */
const std::string Format() const const std::string Format() const
{ {
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>";
} }
} }
...@@ -113,9 +133,10 @@ public: ...@@ -113,9 +133,10 @@ public:
*/ */
DIRECTION_45 Opposite() const DIRECTION_45 Opposite() const
{ {
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];
} }
...@@ -124,20 +145,20 @@ public: ...@@ -124,20 +145,20 @@ public:
* Returns the type of angle between directions (this) and aOther. * Returns the type of angle between directions (this) and aOther.
* @param aOther direction to compare angle with * @param aOther direction to compare angle with
*/ */
AngleType Angle(const DIRECTION_45& aOther) const AngleType Angle( const DIRECTION_45& aOther ) const
{ {
if(m_dir == UNDEFINED || aOther.m_dir == UNDEFINED) if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
return ANG_UNDEFINED; return ANG_UNDEFINED;
int d = std::abs(m_dir - aOther.m_dir); int d = std::abs( m_dir - aOther.m_dir );
if(d == 1 || d == 7) if( d == 1 || d == 7 )
return ANG_OBTUSE; return ANG_OBTUSE;
else if(d == 2 || d == 6) else if( d == 2 || d == 6 )
return ANG_RIGHT; return ANG_RIGHT;
else if(d == 3 || d == 5) else if( d == 3 || d == 5 )
return ANG_ACUTE; return ANG_ACUTE;
else if(d == 4) else if( d == 4 )
return ANG_HALF_FULL; return ANG_HALF_FULL;
else else
return ANG_STRAIGHT; return ANG_STRAIGHT;
...@@ -147,9 +168,9 @@ public: ...@@ -147,9 +168,9 @@ public:
* Function IsObtuse() * Function IsObtuse()
* @return true, when (this) forms an obtuse angle with aOther * @return true, when (this) forms an obtuse angle with aOther
*/ */
bool IsObtuse(const DIRECTION_45& aOther) const bool IsObtuse( const DIRECTION_45& aOther ) const
{ {
return Angle(aOther) == ANG_OBTUSE; return Angle( aOther ) == ANG_OBTUSE;
} }
/** /**
...@@ -159,7 +180,7 @@ public: ...@@ -159,7 +180,7 @@ public:
*/ */
bool IsDiagonal() const bool IsDiagonal() const
{ {
return (m_dir % 2) == 1; return ( m_dir % 2 ) == 1;
} }
/** /**
...@@ -172,51 +193,56 @@ public: ...@@ -172,51 +193,56 @@ 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 );
int sw = sign(aP1.x - aP0.x); int sw = sign( aP1.x - aP0.x );
int sh = sign(aP1.y - aP0.y); int sh = sign( aP1.y - aP0.y );
VECTOR2I mp0, mp1; VECTOR2I mp0, mp1;
// we are more horizontal than vertical? // we are more horizontal than vertical?
if(w > h) if( w > h )
{
mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E
mp1 = VECTOR2I( h * sw, h * sh ); // direction: NE
}
else
{ {
mp0 = VECTOR2I((w - h) * sw, 0); // direction: E mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N
mp1 = VECTOR2I(h * sw, h * sh); // direction: NE mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
} else {
mp0 = VECTOR2I(0, sh * (h - w)); // direction: N
mp1 = VECTOR2I(sw * w, sh * w); // direction: NE
} }
bool start_diagonal; bool start_diagonal;
if(m_dir == UNDEFINED) if( m_dir == UNDEFINED )
start_diagonal = aStartDiagonal; start_diagonal = aStartDiagonal;
else else
start_diagonal = IsDiagonal(); start_diagonal = IsDiagonal();
SHAPE_LINE_CHAIN pl; SHAPE_LINE_CHAIN pl;
pl.Append(aP0); pl.Append( aP0 );
if (start_diagonal)
pl.Append(aP0 + mp1); if( start_diagonal )
pl.Append( aP0 + mp1 );
else else
pl.Append(aP0 + mp0); pl.Append( aP0 + mp0 );
pl.Append(aP1); pl.Append( aP1 );
pl.Simplify(); pl.Simplify();
return pl; return pl;
}; };
bool operator==(const DIRECTION_45& aOther) const bool operator==( const DIRECTION_45& aOther ) const
{ {
return aOther.m_dir == m_dir; return aOther.m_dir == m_dir;
} }
bool operator!=(const DIRECTION_45& aOther) const bool operator!=( const DIRECTION_45& aOther ) const
{ {
return aOther.m_dir != m_dir; return aOther.m_dir != m_dir;
} }
...@@ -224,16 +250,21 @@ public: ...@@ -224,16 +250,21 @@ 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>
return (T(0) < val) - (val < T(0)); int sign( T val ) const
{
return (T( 0 ) < val) - ( val < T( 0 ) );
} }
/** /**
...@@ -242,47 +273,52 @@ private: ...@@ -242,47 +273,52 @@ private:
* degrees, the direction is rounded to the nearest octant. * degrees, the direction is rounded to the nearest octant.
* @param aVec our vector * @param aVec our vector
*/ */
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;
m_dir = (Directions) ((mag + 22.5) / 45.0); m_dir = (Directions)( ( mag + 22.5 ) / 45.0 );
if( m_dir >= 8 )
m_dir = (Directions)( m_dir - 8 );
if(m_dir >= 8) if( m_dir < 0 )
m_dir = (Directions) (m_dir - 8); m_dir = (Directions)( m_dir + 8 );
if(m_dir < 0)
m_dir = (Directions) (m_dir + 8);
return ; return;
if(aVec.y < 0)
if( aVec.y < 0 )
{ {
if(aVec.x > 0) if( aVec.x > 0 )
m_dir = NE; m_dir = NE;
else if(aVec.x < 0) else if( aVec.x < 0 )
m_dir = NW; m_dir = NW;
else else
m_dir = N; m_dir = N;
} }
else if(aVec.y == 0) else if( aVec.y == 0 )
{ {
if(aVec.x > 0) if( aVec.x > 0 )
m_dir = E; m_dir = E;
else else
m_dir = W; m_dir = W;
} }
else // aVec.y>0 else // aVec.y>0
{ {
if(aVec.x > 0) if( aVec.x > 0 )
m_dir = SE; m_dir = SE;
else if(aVec.x < 0) else if( aVec.x < 0 )
m_dir = SW; m_dir = SW;
else else
m_dir = S; m_dir = S;
...@@ -293,3 +329,4 @@ private: ...@@ -293,3 +329,4 @@ private:
}; };
#endif // __DIRECTION_H #endif // __DIRECTION_H
...@@ -37,42 +37,41 @@ ...@@ -37,42 +37,41 @@
* 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;
PNS_INDEX(); PNS_INDEX();
~PNS_INDEX(); ~PNS_INDEX();
void Add( PNS_ITEM *aItem ); void Add( PNS_ITEM* aItem );
void Remove ( PNS_ITEM *aItem ); void Remove( PNS_ITEM* aItem );
void Replace ( PNS_ITEM *aOldItem, PNS_ITEM *aNewItem ); void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
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 );
void Clear(); void Clear();
NetItemsList* GetItemsForNet ( int aNet ) ; NetItemsList* GetItemsForNet( int aNet );
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;
...@@ -81,161 +80,184 @@ private: ...@@ -81,161 +80,184 @@ private:
static const int SI_PadsTop = 0; static const int SI_PadsTop = 0;
static const int SI_PadsBottom = 1; static const int SI_PadsBottom = 1;
template<class Visitor> template <class Visitor>
int querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v); int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v );
ItemShapeIndex *getSubindex( const PNS_ITEM *aItem ); ItemShapeIndex* getSubindex( const PNS_ITEM* aItem );
ItemShapeIndex *m_subIndices[ MaxSubIndices ]; ItemShapeIndex* m_subIndices[MaxSubIndices];
std::map<int, NetItemsList> m_netMap; std::map<int, NetItemsList> m_netMap;
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;
const PNS_LAYERSET l = aItem->GetLayers(); const PNS_LAYERSET l = aItem->GetLayers();
switch(aItem->GetKind()) switch( aItem->GetKind() )
{ {
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() )
idx_n = SI_Multilayer; idx_n = SI_Multilayer;
else if (l.Start() == 0) // fixme: use kicad layer codes else if( l.Start() == 0 ) // fixme: use kicad layer codes
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);
if(!m_subIndices[idx_n]) assert( idx_n >= 0 && idx_n < MaxSubIndices );
if( !m_subIndices[idx_n] )
m_subIndices[idx_n] = new ItemShapeIndex; m_subIndices[idx_n] = new ItemShapeIndex;
return m_subIndices[idx_n]; return m_subIndices[idx_n];
} }
void PNS_INDEX::Add( PNS_ITEM *aItem )
{
ItemShapeIndex *idx = getSubindex(aItem);
void PNS_INDEX::Add( PNS_ITEM* 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);
m_allItems.erase (aItem); idx->Remove( aItem );
m_allItems.erase( aItem );
int net = aItem->GetNet(); int net = aItem->GetNet();
if(net >= 0 && m_netMap.find(net) != m_netMap.end()) if( net >= 0 && m_netMap.find( net ) != m_netMap.end() )
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();
if(layers.IsMultilayer()) if( layers.IsMultilayer() )
{ {
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 )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v);
} else { for( int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v );
}
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++)
total += querySingle(i, aShape, aMinDistance, v); for( int i = 0; i < MaxSubIndices; i++ )
total += querySingle( i, aShape, aMinDistance, v );
return total; return total;
} }
void PNS_INDEX::Clear() 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
...@@ -21,22 +21,25 @@ ...@@ -21,22 +21,25 @@
#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 )
return false; return false;
// check if we are not on completely different layers first // check if we are not on completely different layers first
if (!m_layers.Overlaps (aOther->m_layers)) if( !m_layers.Overlaps( aOther->m_layers ) )
return false; return false;
return GetShape()->Collide ( aOther->GetShape(), aClearance ); return GetShape()->Collide( aOther->GetShape(), aClearance );
// 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;
...@@ -44,29 +47,43 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V ...@@ -44,29 +47,43 @@ bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, V
// special case for "head" line with a via attached at the end. // special case for "head" line with a via attached at the end.
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())
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV ); if( line->EndsWithVia() )
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()
{ {
} }
...@@ -41,11 +41,11 @@ class PNS_NODE; ...@@ -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,
...@@ -54,7 +54,7 @@ public: ...@@ -54,7 +54,7 @@ public:
ANY = 0xff ANY = 0xff
}; };
PNS_ITEM(PnsKind aKind) PNS_ITEM( PnsKind aKind )
{ {
m_net = UnusedNet; m_net = UnusedNet;
m_movable = true; m_movable = true;
...@@ -77,79 +77,82 @@ public: ...@@ -77,79 +77,82 @@ public:
virtual ~PNS_ITEM(); virtual ~PNS_ITEM();
virtual PNS_ITEM *Clone() const = 0; virtual PNS_ITEM* Clone() const = 0;
///> Returns a convex polygon "hull" of a the item, that is used as the walkaround ///> Returns a convex polygon "hull" of a the item, that is used as the walkaround
/// path. /// path.
/// aClearance defines how far from the body of the item the hull should be, /// aClearance defines how far from the body of the item the hull should be,
/// aWalkaroundThickness is the width of the line that walks around this hull. /// aWalkaroundThickness is the width of the line that walks around this hull.
virtual const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const
{ {
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; }
const std::string GetKindStr() const; const std::string GetKindStr() const;
///> Gets/Sets the corresponding parent object in the host application's model (pcbnew) ///> Gets/Sets the corresponding parent object in the host application's model (pcbnew)
void SetParent(BOARD_ITEM *aParent) { m_parent = aParent; } void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; }
BOARD_ITEM *GetParent() const { return m_parent; } BOARD_ITEM* GetParent() const { return m_parent; }
///> Net accessors ///> Net accessors
int GetNet() const { return m_net; } int GetNet() const { return m_net; }
void SetNet(int aNet) { m_net = aNet; } void SetNet( int aNet ) { m_net = aNet; }
///> 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; }
bool BelongsTo (PNS_NODE *aNode) const { return m_owner == aNode; } bool BelongsTo( PNS_NODE* aNode ) const { return m_owner == aNode; }
PNS_NODE *GetOwner() const { return m_owner; } PNS_NODE* GetOwner() const { return m_owner; }
///> Sets the world that is used for collision resolution. ///> Sets the world that is used for collision resolution.
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;
PNS_NODE *m_world; PNS_NODE* m_world;
PNS_NODE *m_owner; PNS_NODE* m_owner;
PNS_LAYERSET m_layers; PNS_LAYERSET m_layers;
bool m_movable; bool m_movable;
int m_net; int m_net;
}; };
#endif // __PNS_ITEM_H #endif // __PNS_ITEM_Ha
...@@ -25,48 +25,57 @@ ...@@ -25,48 +25,57 @@
PNS_ITEMSET::PNS_ITEMSET() PNS_ITEMSET::PNS_ITEMSET()
{ {
} }
PNS_ITEMSET::~PNS_ITEMSET() PNS_ITEMSET::~PNS_ITEMSET()
{ {
} }
PNS_ITEMSET& PNS_ITEMSET::FilterLayers ( int aStart, int aEnd )
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
{ {
ItemVector newItems; ItemVector newItems;
PNS_LAYERSET l; PNS_LAYERSET l;
if(aEnd < 0)
l = PNS_LAYERSET(aStart); if( aEnd < 0 )
l = PNS_LAYERSET( aStart );
else else
l = PNS_LAYERSET(aStart, aEnd); l = PNS_LAYERSET( aStart, aEnd );
BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetLayers().Overlaps( l ) )
newItems.push_back( item );
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetLayers(). Overlaps ( l ))
newItems.push_back(item);
m_items = newItems; m_items = newItems;
return *this; return *this;
} }
PNS_ITEMSET& PNS_ITEMSET::FilterKinds ( int aKindMask )
PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
{ {
ItemVector newItems; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if(item->GetKind() & aKindMask )
newItems.push_back(item); if( item->GetKind() & aKindMask )
newItems.push_back( item );
m_items = newItems; m_items = newItems;
return *this; return *this;
} }
PNS_ITEMSET& PNS_ITEMSET::FilterNet ( int aNet )
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
{ {
ItemVector newItems; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if(item->GetNet() == aNet)
newItems.push_back(item); if( item->GetNet() == aNet )
newItems.push_back( item );
m_items = newItems; m_items = newItems;
return *this; return *this;
} }
......
...@@ -28,35 +28,36 @@ ...@@ -28,35 +28,36 @@
/** /**
* Class PNS_ITEMSET * Class PNS_ITEMSET
* *
* Holds a list of board items, that can be filtered against net, kinds, layers, etc. * Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/ **/
class PNS_ITEMSET class PNS_ITEMSET
{ {
public: public:
typedef std::vector<PNS_ITEM*> ItemVector;
typedef std::vector<PNS_ITEM *> ItemVector;
PNS_ITEMSET(); PNS_ITEMSET();
~PNS_ITEMSET(); ~PNS_ITEMSET();
ItemVector& Items() { return m_items; } ItemVector& Items() { return m_items; }
PNS_ITEMSET& FilterLayers ( int aStart, int aEnd = -1 ); PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 );
PNS_ITEMSET& FilterKinds ( int aKindMask ); PNS_ITEMSET& FilterKinds( int aKindMask );
PNS_ITEMSET& FilterNet ( int aNet ); PNS_ITEMSET& FilterNet( int aNet );
int Size() { return m_items.size(); } int Size() { return m_items.size(); }
void Add(PNS_ITEM *item) void Add( PNS_ITEM* item )
{ {
m_items.push_back(item); m_items.push_back( item );
} }
PNS_ITEM *Get( int index ) const { return m_items[index]; } PNS_ITEM* Get( int index ) const { return m_items[index]; }
private: private:
ItemVector m_items; ItemVector m_items;
}; };
#endif #endif
...@@ -32,35 +32,38 @@ ...@@ -32,35 +32,38 @@
/** /**
* Class PNS_JOINT * Class PNS_JOINT
* *
* Represents a 2D point on a given set of layers and belonging to a certain net, * Represents a 2D point on a given set of layers and belonging to a certain
* that links together a number of board items. * net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items. * A hash table of joints is used by the router to follow connectivity between
* the items.
**/ **/
class PNS_JOINT : public PNS_ITEM class PNS_JOINT : public PNS_ITEM
{ {
public: public:
typedef std::vector<PNS_ITEM *> LinkedItems; typedef std::vector<PNS_ITEM*> LinkedItems;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed ///> Joints are hashed by their position, layers and net.
struct HashTag { /// Linked items are, obviously, not hashed
struct HashTag
{
VECTOR2I pos; VECTOR2I pos;
int net; int net;
}; };
PNS_JOINT(): PNS_JOINT() :
PNS_ITEM(JOINT) {} PNS_ITEM( JOINT ) {}
PNS_JOINT(const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1): PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
PNS_ITEM(JOINT) int aNet = -1 ) :
PNS_ITEM( JOINT )
{ {
m_tag.pos = aPos; m_tag.pos = aPos;
m_tag.net = aNet; m_tag.net = aNet;
m_layers = aLayers; m_layers = aLayers;
} }
PNS_JOINT(const PNS_JOINT& b): PNS_JOINT( const PNS_JOINT& b ) :
PNS_ITEM(JOINT) PNS_ITEM( JOINT )
{ {
m_layers = b.m_layers; m_layers = b.m_layers;
m_tag.pos = b.m_tag.pos; m_tag.pos = b.m_tag.pos;
...@@ -69,99 +72,111 @@ public: ...@@ -69,99 +72,111 @@ public:
m_layers = b.m_layers; m_layers = b.m_layers;
} }
PNS_ITEM *Clone() const PNS_ITEM* Clone() const
{ {
assert(false); assert( false );
return NULL; return NULL;
} }
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer. ///> Returns true if the joint is a trivial line corner, connecting two
/// segments of the same net, on the same layer.
bool IsLineCorner() const bool IsLineCorner() const
{ {
if(m_linkedItems.size() != 2) if( m_linkedItems.size() != 2 )
return false; return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || m_linkedItems[1]->GetKind() != SEGMENT ) if( m_linkedItems[0]->GetKind() != SEGMENT ||
m_linkedItems[1]->GetKind() != SEGMENT )
return false; return false;
PNS_SEGMENT *seg1 = static_cast<PNS_SEGMENT *> (m_linkedItems[0]); PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]);
PNS_SEGMENT *seg2 = static_cast<PNS_SEGMENT *> (m_linkedItems[1]); PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]);
// joints between segments of different widths are not trivial. // joints between segments of different widths are not trivial.
return (seg1->GetWidth() == seg2->GetWidth()); return seg1->GetWidth() == seg2->GetWidth();
} }
///> Links the joint to a given board item (when it's added to the PNS_NODE) ///> Links the joint to a given board item (when it's added to the PNS_NODE)
void Link ( PNS_ITEM *aItem ) void Link( PNS_ITEM* aItem )
{ {
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem); LinkedItems::iterator f = std::find( m_linkedItems.begin(),
if(f != m_linkedItems.end()) m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() )
return; return;
m_linkedItems.push_back(aItem);
m_linkedItems.push_back( aItem );
} }
///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE) ///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE)
///> Returns true if the joint became dangling after unlinking. ///> Returns true if the joint became dangling after unlinking.
bool Unlink ( PNS_ITEM *aItem ) bool Unlink( PNS_ITEM* aItem )
{ {
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem); LinkedItems::iterator f = std::find( m_linkedItems.begin(),
if(f != m_linkedItems.end()) m_linkedItems.end(), aItem );
m_linkedItems.erase(f);
return (m_linkedItems.size() == 0); if( f != m_linkedItems.end() )
m_linkedItems.erase( f );
return m_linkedItems.size() == 0;
} }
///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns ///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
///> NULL, indicating the end of line. ///> NULL, indicating the end of line.
PNS_SEGMENT* NextSegment( PNS_SEGMENT* aCurrent) const PNS_SEGMENT* NextSegment( PNS_SEGMENT* aCurrent ) const
{ {
if(!IsLineCorner()) if( !IsLineCorner() )
return NULL; return NULL;
return static_cast<PNS_SEGMENT *> (m_linkedItems [ m_linkedItems[0] == aCurrent ? 1 : 0 ] ); return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
} }
/// trivial accessors /// trivial accessors
const HashTag& GetTag() const { return m_tag; } const HashTag& GetTag() const { return m_tag; }
const VECTOR2I& GetPos() const { return m_tag.pos; } const VECTOR2I& GetPos() const { return m_tag.pos; }
int GetNet() const { return m_tag.net; } int GetNet() const { return m_tag.net; }
LinkedItems & GetLinkList() { return m_linkedItems; }; LinkedItems& GetLinkList() { return m_linkedItems; };
///> Returns the number of linked items of types listed in aMask. ///> Returns the number of linked items of types listed in aMask.
int LinkCount( int aMask = -1 ) const int LinkCount( int aMask = -1 ) const
{ {
int n = 0; int n = 0;
for(LinkedItems::const_iterator i = m_linkedItems.begin(); i!= m_linkedItems.end(); ++i)
for( LinkedItems::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i )
if( (*i)->GetKind() & aMask ) if( (*i)->GetKind() & aMask )
n++; n++;
return n; return n;
} }
void Dump() const; void Dump() const;
bool operator==(const PNS_JOINT& rhs) const bool operator==( const PNS_JOINT& rhs ) const
{ {
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net; return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net;
} }
void Merge( const PNS_JOINT& aJoint ) void Merge( const PNS_JOINT& aJoint )
{ {
if(!Overlaps(aJoint)) if( !Overlaps( aJoint ) )
return; return;
m_layers.Merge (aJoint.m_layers); m_layers.Merge( aJoint.m_layers );
// fixme: duplicate links (?) // fixme: duplicate links (?)
for(LinkedItems::const_iterator i =aJoint.m_linkedItems.begin(); i!=aJoint.m_linkedItems.end();++i) for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin();
m_linkedItems.push_back(*i); i != aJoint.m_linkedItems.end(); ++i )
m_linkedItems.push_back( *i );
} }
bool Overlaps(const PNS_JOINT& rhs) const bool Overlaps( const PNS_JOINT& rhs ) const
{ {
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net && m_layers.Overlaps(rhs.m_layers); return m_tag.pos == rhs.m_tag.pos &&
m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
} }
private: private:
///> hash tag for unordered_multimap ///> hash tag for unordered_multimap
HashTag m_tag; HashTag m_tag;
...@@ -171,18 +186,22 @@ private: ...@@ -171,18 +186,22 @@ private:
// hash function & comparison operator for boost::unordered_map<> // hash function & comparison operator for boost::unordered_map<>
inline bool operator==(PNS_JOINT::HashTag const& p1, PNS_JOINT::HashTag const& p2) inline bool operator==( PNS_JOINT::HashTag const& p1,
PNS_JOINT::HashTag const& p2 )
{ {
return p1.pos == p2.pos && p1.net == p2.net; return p1.pos == p2.pos && p1.net == p2.net;
} }
inline std::size_t hash_value(PNS_JOINT::HashTag const& p)
inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
{ {
std::size_t seed = 0; std::size_t seed = 0;
boost::hash_combine(seed, p.pos.x); boost::hash_combine( seed, p.pos.x );
boost::hash_combine(seed, p.pos.y); boost::hash_combine( seed, p.pos.y );
boost::hash_combine(seed, p.net); boost::hash_combine( seed, p.net );
return seed; return seed;
} }
#endif // __PNS_JOINT_H #endif // __PNS_JOINT_H
...@@ -28,91 +28,93 @@ ...@@ -28,91 +28,93 @@
* *
* Represents a contiguous set of PCB layers. * Represents a contiguous set of PCB layers.
*/ */
class PNS_LAYERSET class PNS_LAYERSET
{ {
public: public:
PNS_LAYERSET() :
PNS_LAYERSET(): m_start( -1 ),
m_start(-1), m_end( -1 )
m_end(-1)
{}; {};
PNS_LAYERSET (int aStart, int aEnd) PNS_LAYERSET( int aStart, int aEnd )
{ {
if(aStart > aEnd) if( aStart > aEnd )
std::swap(aStart, aEnd); std::swap( aStart, aEnd );
m_start = aStart; m_start = aStart;
m_end = aEnd; m_end = aEnd;
} }
PNS_LAYERSET (int aLayer) PNS_LAYERSET( int aLayer )
{ {
m_start = m_end = aLayer; m_start = m_end = aLayer;
} }
PNS_LAYERSET(const PNS_LAYERSET &b) : PNS_LAYERSET( const PNS_LAYERSET& b ) :
m_start(b.m_start), m_start( b.m_start ),
m_end (b.m_end) m_end( b.m_end )
{} {}
~PNS_LAYERSET () {}; ~PNS_LAYERSET() {};
const PNS_LAYERSET& operator= ( const PNS_LAYERSET& b) const PNS_LAYERSET& operator=( const PNS_LAYERSET& b )
{ {
m_start = b.m_start; m_start = b.m_start;
m_end = b.m_end; m_end = b.m_end;
return *this; return *this;
} }
bool Overlaps ( const PNS_LAYERSET& aOther ) const bool Overlaps( const PNS_LAYERSET& aOther ) const
{ {
return m_end >= aOther.m_start && m_start <= aOther.m_end; return m_end >= aOther.m_start && m_start <= aOther.m_end;
} }
bool Overlaps ( const int aLayer ) const bool Overlaps( const int aLayer ) const
{ {
return aLayer >= m_start && aLayer <= m_end; return aLayer >= m_start && aLayer <= m_end;
} }
bool IsMultilayer ( ) const bool IsMultilayer() const
{ {
return m_start != m_end; return m_start != m_end;
} }
int Start() const { int Start() const
{
return m_start; return m_start;
} }
int End() const { int End() const
{
return m_end; return m_end;
} }
void Merge ( const PNS_LAYERSET& aOther ) void Merge( const PNS_LAYERSET& aOther )
{ {
if(m_start < 0 || m_end < 0) if( m_start < 0 || m_end < 0 )
{ {
m_start = aOther.m_start; m_start = aOther.m_start;
m_end = aOther.m_end; m_end = aOther.m_end;
return; return;
} }
if(aOther.m_start < m_start) if( aOther.m_start < m_start )
m_start = aOther.m_start; m_start = aOther.m_start;
if(aOther.m_end > m_end)
if( aOther.m_end > m_end )
m_end = aOther.m_end; m_end = aOther.m_end;
} }
///> Shortcut for comparisons/overlap tests ///> Shortcut for comparisons/overlap tests
static PNS_LAYERSET All() static PNS_LAYERSET All()
{ {
return PNS_LAYERSET(0, 256); return PNS_LAYERSET( 0, 256 );
} }
private: private:
int m_start; int m_start;
int m_end; int m_end;
}; };
#endif // __PNS_LAYERSET_H #endif // __PNS_LAYERSET_H
This diff is collapsed.
...@@ -38,46 +38,48 @@ class PNS_VIA; ...@@ -38,46 +38,48 @@ class PNS_VIA;
/** /**
* Class PNS_LINE * Class PNS_LINE
* *
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads, * Represents a track on a PCB, connecting two non-trivial joints (that is,
* junctions between multiple traces or two traces different widths and combinations of these). * vias, pads, junctions between multiple traces or two traces different widths
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on * and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* a via/pad/segment that belongs/begins them. * Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
* *
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments * PNS_LINEs can be either loose (consisting of segments that do not belong to
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends. * any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends.
* *
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff. * A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/ */
class PNS_LINE : public PNS_ITEM class PNS_LINE : public PNS_ITEM
{ {
public: public:
typedef std::vector<PNS_SEGMENT *> LinkedSegments; typedef std::vector<PNS_SEGMENT*> LinkedSegments;
PNS_LINE (): PNS_LINE() :
PNS_ITEM(LINE) PNS_ITEM( LINE )
{ {
m_segmentRefs = NULL; m_segmentRefs = NULL;
m_hasVia = false; m_hasVia = false;
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
}; };
PNS_LINE (int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine) : PNS_LINE( int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine ) :
PNS_ITEM(LINE) PNS_ITEM( LINE )
{ {
m_line = aLine; m_line = aLine;
m_width = aWidth; m_width = aWidth;
m_segmentRefs = NULL; m_segmentRefs = NULL;
m_hasVia = false; m_hasVia = false;
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
SetLayer(aLayer); SetLayer( aLayer );
} }
PNS_LINE(const PNS_LINE& aOther) : PNS_LINE( const PNS_LINE& aOther ) :
PNS_ITEM(aOther), PNS_ITEM( aOther ),
m_line(aOther.m_line), m_line( aOther.m_line ),
m_width(aOther.m_width) m_width( aOther.m_width )
{ {
m_net = aOther.m_net; m_net = aOther.m_net;
m_movable = aOther.m_movable; m_movable = aOther.m_movable;
...@@ -94,10 +96,10 @@ public: ...@@ -94,10 +96,10 @@ public:
* copies properties (net, layers from a base line), and replaces the shape * copies properties (net, layers from a base line), and replaces the shape
* by aLine * by aLine
**/ **/
PNS_LINE(const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine) : PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) :
PNS_ITEM(aBase), PNS_ITEM( aBase ),
m_line(aLine), m_line( aLine ),
m_width(aBase.m_width) m_width( aBase.m_width )
{ {
m_net = aBase.m_net; m_net = aBase.m_net;
m_layers = aBase.m_layers; m_layers = aBase.m_layers;
...@@ -106,64 +108,68 @@ public: ...@@ -106,64 +108,68 @@ public:
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
} }
~PNS_LINE () ~PNS_LINE()
{ {
if(m_segmentRefs) if( m_segmentRefs )
delete m_segmentRefs; delete m_segmentRefs;
}; };
virtual PNS_LINE *Clone() const ; virtual PNS_LINE* Clone() const;
///> clones the line without cloning the shape (just the properties - net, width, layers, etc.) ///> clones the line without cloning the shape
PNS_LINE *CloneProperties() const ; ///> (just the properties - net, width, layers, etc.)
PNS_LINE* CloneProperties() const;
int GetLayer() const { return GetLayers().Start(); } int GetLayer() const { return GetLayers().Start(); }
///> Geometry accessors ///> Geometry accessors
void SetShape(const SHAPE_LINE_CHAIN& aLine) { m_line = aLine; } void SetShape( const SHAPE_LINE_CHAIN& aLine ) { m_line = aLine; }
const SHAPE* GetShape() const { return &m_line; } const SHAPE* GetShape() const { return &m_line; }
SHAPE_LINE_CHAIN& GetLine() { return m_line; } SHAPE_LINE_CHAIN& GetLine() { return m_line; }
const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; } const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
///> Width accessors ///> Width accessors
void SetWidth( int aWidth ) { m_width = aWidth; } void SetWidth( int aWidth ) { m_width = aWidth; }
int GetWidth () const { return m_width; } int GetWidth() const { return m_width; }
///> Links a segment from a PNS_NODE to this line, making it owned by the node ///> Links a segment from a PNS_NODE to this line, making it owned by the node
void LinkSegment(PNS_SEGMENT *aSeg) void LinkSegment( PNS_SEGMENT* aSeg )
{ {
if(!m_segmentRefs) if( !m_segmentRefs )
m_segmentRefs = new std::vector<PNS_SEGMENT *> (); m_segmentRefs = new std::vector<PNS_SEGMENT*> ();
m_segmentRefs->push_back(aSeg);
m_segmentRefs->push_back( aSeg );
} }
///> Returns a list of segments from the owning node that constitute this line (or NULL if ///> Returns a list of segments from the owning node that constitute this
///> the line is loose) ///> line (or NULL if the line is loose)
LinkedSegments* GetLinkedSegments() LinkedSegments* GetLinkedSegments()
{ {
return m_segmentRefs; return m_segmentRefs;
} }
bool ContainsSegment (PNS_SEGMENT *aSeg) const bool ContainsSegment( PNS_SEGMENT* aSeg ) const
{ {
if (!m_segmentRefs) if( !m_segmentRefs )
return false; return false;
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end(); return std::find( m_segmentRefs->begin(), m_segmentRefs->end(),
aSeg ) != m_segmentRefs->end();
} }
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision. ///> Returns this line, but clipped to the nearest obstacle
const PNS_LINE ClipToNearestObstacle( PNS_NODE *aNode ) const; ///> along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const;
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER) ///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
bool MergeObtuseSegments(); bool MergeObtuseSegments();
bool MergeSegments(); bool MergeSegments();
///> Returns the number of corners of angles specified by mask aAngles. ///> Returns the number of corners of angles specified by mask aAngles.
int CountCorners(int aAngles); int CountCorners( int aAngles );
///> Calculates a line thightly wrapping a convex hull 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 ///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle ///> aWalkaroundPath = path around the obstacle
///> aPostPath = past from obstacle till the end ///> aPostPath = past from obstacle till the end
...@@ -179,13 +185,16 @@ public: ...@@ -179,13 +185,16 @@ public:
bool aCw ) const; bool aCw ) const;
bool Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const; bool Walkaround( SHAPE_LINE_CHAIN obstacle,
SHAPE_LINE_CHAIN& pre,
SHAPE_LINE_CHAIN& walk,
SHAPE_LINE_CHAIN& post,
bool cw ) const;
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle, void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath, SHAPE_LINE_CHAIN& aPath,
bool aCw ) const; bool aCw ) const;
bool Is45Degree(); bool Is45Degree();
///> Prints out all linked segments ///> Prints out all linked segments
...@@ -193,34 +202,37 @@ public: ...@@ -193,34 +202,37 @@ public:
bool EndsWithVia() const { return m_hasVia; } bool EndsWithVia() const { return m_hasVia; }
void AppendVia ( const PNS_VIA &aVia ) { void AppendVia( const PNS_VIA& aVia )
{
m_hasVia = true; m_hasVia = true;
m_via = aVia; m_via = aVia;
m_via.SetNet ( m_net ) ; m_via.SetNet( m_net );
} }
void RemoveVia() { m_hasVia = false; } void RemoveVia() { m_hasVia = false; }
const PNS_VIA& GetVia() const { return m_via; } const PNS_VIA& GetVia() const { return m_via; }
void SetAffectedRange ( int aStart, int aEnd ) void SetAffectedRange( int aStart, int aEnd )
{ {
m_affectedRangeStart = aStart; m_affectedRangeStart = aStart;
m_affectedRangeEnd = aEnd; m_affectedRangeEnd = aEnd;
} }
void ClearAffectedRange ( ) void ClearAffectedRange()
{ {
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
} }
bool GetAffectedRange ( int& aStart, int& aEnd ) bool GetAffectedRange( int& aStart, int& aEnd )
{ {
if(m_affectedRangeStart >= 0) if( m_affectedRangeStart >= 0 )
{ {
aStart = m_affectedRangeStart; aStart = m_affectedRangeStart;
aEnd = m_affectedRangeEnd; aEnd = m_affectedRangeEnd;
return true; return true;
} else { }
else
{
aStart = 0; aStart = 0;
aEnd = m_line.PointCount(); aEnd = m_line.PointCount();
return false; return false;
...@@ -228,8 +240,9 @@ public: ...@@ -228,8 +240,9 @@ public:
} }
private: private:
bool onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const; bool onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, bool& is_vertex ) const;
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const; bool walkScan( const SHAPE_LINE_CHAIN& line, const SHAPE_LINE_CHAIN& obstacle,
bool reverse, VECTOR2I& ip, int& index_o, int& index_l, bool& is_vertex ) const;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line. ///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments* m_segmentRefs; LinkedSegments* m_segmentRefs;
...@@ -238,6 +251,7 @@ private: ...@@ -238,6 +251,7 @@ private:
SHAPE_LINE_CHAIN m_line; SHAPE_LINE_CHAIN m_line;
int m_width; int m_width;
///> Via at the end and a flag indicating if it's enabled. ///> Via at the end and a flag indicating if it's enabled.
PNS_VIA m_via; PNS_VIA m_via;
bool m_hasVia; bool m_hasVia;
...@@ -246,6 +260,5 @@ private: ...@@ -246,6 +260,5 @@ private:
int m_affectedRangeEnd; int m_affectedRangeEnd;
}; };
#endif // __PNS_LINE_H #endif // __PNS_LINE_H
This diff is collapsed.
...@@ -39,17 +39,18 @@ class PNS_ROUTER_BASE; ...@@ -39,17 +39,18 @@ class PNS_ROUTER_BASE;
/** /**
* Class PNS_LINE_PLACER * Class PNS_LINE_PLACER
* *
* Interactively routes a single track. Runs shove and walkaround algorithms when needed. * Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/ */
class PNS_LINE_PLACER class PNS_LINE_PLACER
{ {
public: public:
PNS_LINE_PLACER( PNS_NODE *aWorld ); PNS_LINE_PLACER( PNS_NODE* aWorld );
~PNS_LINE_PLACER(); ~PNS_LINE_PLACER();
///> Appends a via at the end of currently placed line. ///> Appends a via at the end of currently placed line.
void AddVia ( bool aEnabled, int aDiameter, int aDrill ) void AddVia( bool aEnabled, int aDiameter, int aDrill )
{ {
m_viaDiameter = aDiameter; m_viaDiameter = aDiameter;
m_viaDrill = aDrill; m_viaDrill = aDrill;
...@@ -57,100 +58,198 @@ class PNS_LINE_PLACER ...@@ -57,100 +58,198 @@ class PNS_LINE_PLACER
} }
///> Starts placement of a line at point aStart. ///> Starts placement of a line at point aStart.
void StartPlacement(const VECTOR2I& aStart, int aNet, int aWidth, int aLayer); void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer );
///> Updates the routed line with a new ending point. /**
bool Route(const VECTOR2I& aP); * 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 ///> Sets initial routing direction/posture
void SetInitialDirection(const DIRECTION_45& aDirection); void SetInitialDirection( const DIRECTION_45& aDirection );
void ApplySettings ( const PNS_ROUTING_SETTINGS& aSettings ); void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings );
///> Returns the "head" of the line being placed, that is the volatile part that has not been settled yet ///> Returns the "head" of the line being placed, that is the volatile part
///> that has not been settled yet
const PNS_LINE& GetHead() const { return m_head; } const PNS_LINE& GetHead() const { return m_head; }
///> Returns the "tail" of the line being placed the part that has been fixed already (follow mouse mode only) ///> Returns the "tail" of the line being placed the part that has been
///> fixed already (follow mouse mode only)
const PNS_LINE& GetTail() const { return m_tail; } const PNS_LINE& GetTail() const { return m_tail; }
///> Returns the whole routed line ///> Returns the whole routed line
const PNS_LINE GetTrace() const; const PNS_LINE GetTrace() const;
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions. ///> Returns the current end of the line being placed. It may not be equal
///> to the cursor position due to collisions.
const VECTOR2I& CurrentEnd() const const VECTOR2I& CurrentEnd() const
{ {
if(m_head.GetCLine().PointCount() > 0) if( m_head.GetCLine().PointCount() > 0 )
return m_head.GetCLine().CPoint(-1); return m_head.GetCLine().CPoint( -1 );
else if(m_tail.GetCLine().PointCount() > 0) else if( m_tail.GetCLine().PointCount() > 0 )
return m_tail.GetCLine().CPoint(-1); return m_tail.GetCLine().CPoint( -1 );
else else
return m_p_start; return m_p_start;
} }
///> Returns all items in the world that have been affected by the routing
///> Returns all items in the world that have been affected by the routing operation. Used ///> operation. Used to update data structures of the host application
/// to update data structures of the host application void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded); PNS_NODE::ItemVector& aAdded );
///> Toggles the current posture (straight/diagonal) of the trace head. ///> Toggles the current posture (straight/diagonal) of the trace head.
void FlipPosture(); void FlipPosture();
///> Returns the most recent world state ///> Returns the most recent world state
PNS_NODE *GetCurrentNode() const; PNS_NODE* GetCurrentNode() const;
private:
private:
static const double m_shoveLengthThreshold = 1.7; static const double m_shoveLengthThreshold = 1.7;
bool handleViaPlacement ( PNS_LINE& aHead ); bool handleViaPlacement( PNS_LINE& aHead );
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle
* (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool checkObtusity( const SEG& a, const SEG& b ) const;
bool checkObtusity(const SEG& a, const SEG& b) const; /**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the
* tail up to the intersecting segment and fixes the head direction to match
* the last segment before the cut.
* @return true if the line has been changed.
*/
bool handleSelfIntersections(); bool handleSelfIntersections();
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards
* wrs to the current tail direction.
* @return true if the line has been changed.
*/
bool handlePullback(); bool handlePullback();
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
bool mergeHead(); bool mergeHead();
bool reduceTail(const VECTOR2I& aEnd);
/**
* 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(); void fixHeadPosture();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool optimizeTailHeadTransition(); bool optimizeTailHeadTransition();
bool routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround = true); /**
void routeStep(const VECTOR2I& aP); * 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.) ///> routing mode (walkaround, shove, etc.)
PNS_MODE m_mode; PNS_MODE m_mode;
///> follow mouse trail by attaching new segments to the head as the cursor moves
///> follow mouse trail by attaching new segments to the head
///> as the cursor moves
bool m_follow_mouse; bool m_follow_mouse;
///> mouse smoothing active ///> mouse smoothing active
bool m_smooth_mouse; bool m_smooth_mouse;
///> mouse smoothing step (in world units) ///> mouse smoothing step (in world units)
int m_smoothing_step; int m_smoothing_step;
///> current routing direction ///> current routing direction
DIRECTION_45 m_direction; DIRECTION_45 m_direction;
///> routing direction for new traces ///> routing direction for new traces
DIRECTION_45 m_initial_direction; DIRECTION_45 m_initial_direction;
///> routing "head": volatile part of the track from the previously ///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination /// analyzed point to the current routing destination
PNS_LINE m_head; PNS_LINE m_head;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles ///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE m_tail; PNS_LINE m_tail;
///> current algorithm iteration ///> current algorithm iteration
int m_iteration; int m_iteration;
///> pointer to world to search colliding items ///> pointer to world to search colliding items
PNS_NODE *m_world; PNS_NODE* m_world;
///> current routing start point (end of tail, beginning of head) ///> current routing start point (end of tail, beginning of head)
VECTOR2I m_p_start; VECTOR2I m_p_start;
///> The shove engine ///> The shove engine
PNS_SHOVE *m_shove; PNS_SHOVE* m_shove;
///> Current world state ///> Current world state
PNS_NODE *m_currentNode; PNS_NODE* m_currentNode;
///> Are we placing a via? ///> Are we placing a via?
bool m_placingVia; bool m_placingVia;
///> current via diameter ///> current via diameter
int m_viaDiameter; int m_viaDiameter;
///> current via drill ///> current via drill
int m_viaDrill; int m_viaDrill;
///> walkaround algorithm iteration limit ///> walkaround algorithm iteration limit
int m_walkaroundIterationLimit; int m_walkaroundIterationLimit;
///> smart pads optimizer enabled. ///> smart pads optimizer enabled.
bool m_smartPads; bool m_smartPads;
}; };
#endif // __PNS_LINE_PLACER_H #endif // __PNS_LINE_PLACER_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
#define __PNS_ROUTER_SETTINGS #define __PNS_ROUTER_SETTINGS
///> Routing modes ///> Routing modes
enum PNS_MODE { enum PNS_MODE
{
RM_Ignore = 0, ///> Ignore collisions RM_Ignore = 0, ///> Ignore collisions
RM_Shove, ///> Only shove RM_Shove, ///> Only shove
RM_Walkaround, ///> Only walkaround RM_Walkaround, ///> Only walkaround
...@@ -31,7 +32,7 @@ enum PNS_MODE { ...@@ -31,7 +32,7 @@ enum PNS_MODE {
class PNS_ROUTING_SETTINGS class PNS_ROUTING_SETTINGS
{ {
public: public:
PNS_MODE m_routingMode; PNS_MODE m_routingMode;
bool m_removeLoops; bool m_removeLoops;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -29,24 +29,26 @@ ...@@ -29,24 +29,26 @@
#include "pns_item.h" #include "pns_item.h"
class PNS_SOLID : public PNS_ITEM { class PNS_SOLID : public PNS_ITEM
{
public: public:
PNS_SOLID() : PNS_ITEM(SOLID) PNS_SOLID() : PNS_ITEM( SOLID )
{ {
m_movable = false; m_movable = false;
m_shape = NULL; m_shape = NULL;
} }
PNS_ITEM *Clone() const; PNS_ITEM* Clone() const;
const SHAPE* GetShape() const { return m_shape; } const SHAPE* GetShape() const { return m_shape; }
const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const; const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const;
void SetShape( SHAPE* shape) void SetShape( SHAPE* shape )
{ {
if(m_shape) if( m_shape )
delete m_shape; delete m_shape;
m_shape = shape; m_shape = shape;
} }
...@@ -61,7 +63,6 @@ public: ...@@ -61,7 +63,6 @@ public:
} }
private: private:
VECTOR2I m_center; VECTOR2I m_center;
SHAPE* m_shape; SHAPE* m_shape;
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment