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
../../pcbnew
../../polygon
${INC_AFTER}
)
../../ include
../../ pcbnew
../../ polygon
$ { INC_AFTER }
)
set(PCBNEW_PNS_SRCS
set( PCBNEW_PNS_SRCS
direction.h
pns_via.h
pns_routing_settings.h
......@@ -45,6 +45,7 @@ set(PCBNEW_PNS_SRCS
router_tool.h
router_preview_item.cpp
router_preview_item.h
)
)
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
add_library(pnsrouter STATIC ${PCBNEW_PNS_SRCS})
......@@ -31,7 +31,6 @@
class DIRECTION_45
{
public:
/**
......@@ -39,7 +38,8 @@ public:
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
*/
enum Directions {
enum Directions
{
N = 0,
NE = 1,
E = 2,
......@@ -55,31 +55,32 @@ public:
* Enum AngleType
* Represents kind of angle formed by vectors heading in two DIRECTION_45s.
*/
enum AngleType {
ANG_OBTUSE = 0x1,
ANG_RIGHT = 0x2,
ANG_ACUTE = 0x4,
ANG_STRAIGHT = 0x8,
enum AngleType
{
ANG_OBTUSE = 0x01,
ANG_RIGHT = 0x02,
ANG_ACUTE = 0x04,
ANG_STRAIGHT = 0x08,
ANG_HALF_FULL = 0x10,
ANG_UNDEFINED = 0x20
};
DIRECTION_45(Directions aDir = UNDEFINED): m_dir(aDir) {};
DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {};
/**
* Constructor
* @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
* @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 );
}
......@@ -91,18 +92,37 @@ public:
*/
const std::string Format() const
{
switch(m_dir)
switch( m_dir )
{
case N : return "north";
case NE : return "north-east";
case E : return "east";
case SE : return "south-east";
case S : return "south";
case SW : return "south-west";
case W : return "west";
case NW : return "north-west";
case UNDEFINED : return "undefined";
default: return "<Error>";
case N:
return "north";
case NE:
return "north-east";
case E:
return "east";
case SE:
return "south-east";
case S:
return "south";
case SW:
return "south-west";
case W:
return "west";
case NW:
return "north-west";
case UNDEFINED:
return "undefined";
default:
return "<Error>";
}
}
......@@ -113,9 +133,10 @@ public:
*/
DIRECTION_45 Opposite() const
{
if(m_dir == UNDEFINED)
if( m_dir == 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];
}
......@@ -124,20 +145,20 @@ public:
* Returns the type of angle between directions (this) and aOther.
* @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;
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;
else if(d == 2 || d == 6)
else if( d == 2 || d == 6 )
return ANG_RIGHT;
else if(d == 3 || d == 5)
else if( d == 3 || d == 5 )
return ANG_ACUTE;
else if(d == 4)
else if( d == 4 )
return ANG_HALF_FULL;
else
return ANG_STRAIGHT;
......@@ -147,9 +168,9 @@ public:
* Function IsObtuse()
* @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:
*/
bool IsDiagonal() const
{
return (m_dir % 2) == 1;
return ( m_dir % 2 ) == 1;
}
/**
......@@ -172,51 +193,56 @@ public:
* @param aStartDiagonal whether the first segment has to be diagonal
* @return the trace
*/
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I& aP0, const VECTOR2I &aP1, bool aStartDiagonal = false) const
const SHAPE_LINE_CHAIN BuildInitialTrace( const VECTOR2I& aP0,
const VECTOR2I& aP1,
bool aStartDiagonal = false ) const
{
int w = abs(aP1.x - aP0.x);
int h = abs(aP1.y - aP0.y);
int sw = sign(aP1.x - aP0.x);
int sh = sign(aP1.y - aP0.y);
int w = abs( aP1.x - aP0.x );
int h = abs( aP1.y - aP0.y );
int sw = sign( aP1.x - aP0.x );
int sh = sign( aP1.y - aP0.y );
VECTOR2I mp0, mp1;
// 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
mp1 = VECTOR2I(h * sw, h * sh); // direction: NE
} else {
mp0 = VECTOR2I(0, sh * (h - w)); // direction: N
mp1 = VECTOR2I(sw * w, sh * w); // direction: NE
mp0 = VECTOR2I( 0, sh * (h - w) ); // direction: N
mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
}
bool start_diagonal;
if(m_dir == UNDEFINED)
if( m_dir == UNDEFINED )
start_diagonal = aStartDiagonal;
else
start_diagonal = IsDiagonal();
SHAPE_LINE_CHAIN pl;
pl.Append(aP0);
if (start_diagonal)
pl.Append(aP0 + mp1);
pl.Append( aP0 );
if( start_diagonal )
pl.Append( aP0 + mp1 );
else
pl.Append(aP0 + mp0);
pl.Append( aP0 + mp0 );
pl.Append(aP1);
pl.Append( aP1 );
pl.Simplify();
return pl;
};
bool operator==(const DIRECTION_45& aOther) const
bool operator==( const DIRECTION_45& aOther ) const
{
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;
}
......@@ -224,16 +250,21 @@ public:
const DIRECTION_45 Right() const
{
DIRECTION_45 r;
r.m_dir = (Directions) (m_dir + 1);
if(r.m_dir == NW)
if( r.m_dir == NW )
r.m_dir = N;
return r;
}
private:
template <typename T> int sign(T val) const {
return (T(0) < val) - (val < T(0));
template <typename T>
int sign( T val ) const
{
return (T( 0 ) < val) - ( val < T( 0 ) );
}
/**
......@@ -242,47 +273,52 @@ private:
* degrees, the direction is rounded to the nearest octant.
* @param aVec our vector
*/
void construct(const VECTOR2I& aVec)
void construct( const VECTOR2I& aVec )
{
m_dir = UNDEFINED;
if(aVec.x == 0 && aVec.y == 0)
if( aVec.x == 0 && aVec.y == 0 )
return;
double mag = 360.0 - (180.0 / M_PI * atan2 ((double) aVec.y, (double) aVec.x )) + 90.0;
if (mag >= 360.0)
double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
if( mag >= 360.0 )
mag -= 360.0;
if(mag < 0.0)
if( mag < 0.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)
m_dir = (Directions) (m_dir - 8);
if(m_dir < 0)
m_dir = (Directions) (m_dir + 8);
if( m_dir < 0 )
m_dir = (Directions)( m_dir + 8 );
return ;
if(aVec.y < 0)
return;
if( aVec.y < 0 )
{
if(aVec.x > 0)
if( aVec.x > 0 )
m_dir = NE;
else if(aVec.x < 0)
else if( aVec.x < 0 )
m_dir = NW;
else
m_dir = N;
}
else if(aVec.y == 0)
else if( aVec.y == 0 )
{
if(aVec.x > 0)
if( aVec.x > 0 )
m_dir = E;
else
m_dir = W;
}
else // aVec.y>0
{
if(aVec.x > 0)
if( aVec.x > 0 )
m_dir = SE;
else if(aVec.x < 0)
else if( aVec.x < 0 )
m_dir = SW;
else
m_dir = S;
......@@ -293,3 +329,4 @@ private:
};
#endif // __DIRECTION_H
......@@ -37,42 +37,41 @@
* overlap and improving search time.
**/
class PNS_INDEX {
class PNS_INDEX
{
public:
typedef std::list<PNS_ITEM *> NetItemsList;
typedef SHAPE_INDEX<PNS_ITEM *> ItemShapeIndex;
typedef boost::unordered_set<PNS_ITEM *> ItemSet;
typedef std::list<PNS_ITEM*> NetItemsList;
typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex;
typedef boost::unordered_set<PNS_ITEM*> ItemSet;
PNS_INDEX();
~PNS_INDEX();
void Add( PNS_ITEM *aItem );
void Remove ( PNS_ITEM *aItem );
void Replace ( PNS_ITEM *aOldItem, PNS_ITEM *aNewItem );
void Add( PNS_ITEM* aItem );
void Remove( PNS_ITEM* aItem );
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
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>
int Query( const SHAPE *aShape, int aMinDistance, Visitor &v);
int Query( const SHAPE* aShape, int aMinDistance, Visitor& v );
void Clear();
NetItemsList* GetItemsForNet ( int aNet ) ;
NetItemsList* GetItemsForNet( int aNet );
ItemSet::iterator begin() { return m_allItems.begin(); }
ItemSet::iterator end() { return m_allItems.end(); }
bool Contains ( PNS_ITEM *aItem ) const {
return m_allItems.find(aItem) != m_allItems.end();
bool Contains( PNS_ITEM* aItem ) const
{
return m_allItems.find( aItem ) != m_allItems.end();
}
int Size() const { return m_allItems.size(); }
private:
static const int MaxSubIndices = 64;
static const int SI_Multilayer = 2;
static const int SI_SegDiagonal = 0;
......@@ -81,161 +80,184 @@ private:
static const int SI_PadsTop = 0;
static const int SI_PadsBottom = 1;
template<class Visitor>
int querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v);
template <class Visitor>
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;
ItemSet m_allItems;
};
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;
const PNS_LAYERSET l = aItem->GetLayers();
switch(aItem->GetKind())
switch( aItem->GetKind() )
{
case PNS_ITEM::VIA:
idx_n = SI_Multilayer;
break;
case PNS_ITEM::SOLID:
{
if( l.IsMultilayer() )
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;
else if (l.Start() == 15)
else if( l.Start() == 15 )
idx_n = SI_PadsBottom;
break;
}
case PNS_ITEM::SEGMENT:
case PNS_ITEM::LINE:
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
break;
default:
break;
}
assert(idx_n >= 0 && idx_n < MaxSubIndices);
if(!m_subIndices[idx_n])
assert( idx_n >= 0 && idx_n < MaxSubIndices );
if( !m_subIndices[idx_n] )
m_subIndices[idx_n] = new ItemShapeIndex;
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);
m_allItems.insert(aItem);
idx->Add( aItem );
m_allItems.insert( aItem );
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);
idx->Remove(aItem);
m_allItems.erase (aItem);
ItemShapeIndex* idx = getSubindex( aItem );
idx->Remove( aItem );
m_allItems.erase( aItem );
int net = aItem->GetNet();
if(net >= 0 && m_netMap.find(net) != m_netMap.end())
m_netMap[net].remove(aItem);
if( net >= 0 && m_netMap.find( net ) != m_netMap.end() )
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);
Add(aNewItem);
Remove( aOldItem );
Add( aNewItem );
}
template<class Visitor>
int PNS_INDEX::querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v)
{
if(!m_subIndices[index])
int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v )
{
if( !m_subIndices[index] )
return 0;
return m_subIndices[index] -> Query(aShape, aMinDistance, v, false);
}
return m_subIndices[index]->Query( aShape, aMinDistance, v, false );
}
template<class Visitor>
int PNS_INDEX::Query( const PNS_ITEM *aItem, int aMinDistance, Visitor &v)
{
const SHAPE *shape = aItem->GetShape();
int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v )
{
const SHAPE* shape = aItem->GetShape();
int total = 0;
total += querySingle(SI_Multilayer, shape, aMinDistance, v);
total += querySingle( SI_Multilayer, shape, aMinDistance, v );
const PNS_LAYERSET layers = aItem->GetLayers();
if(layers.IsMultilayer())
if( layers.IsMultilayer() )
{
total += querySingle(SI_PadsTop, shape, aMinDistance, v);
total += querySingle(SI_PadsBottom, shape, aMinDistance, v);
for(int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v);
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
total += querySingle( SI_PadsBottom, 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();
if(l == 0)
total += querySingle(SI_PadsTop, shape, aMinDistance, v);
else if(l == 15)
total += querySingle(SI_PadsBottom, shape, aMinDistance, v);
total += querySingle ( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v);
if( l == 0 )
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
else if( l == 15 )
total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v );
}
return total;
}
}
template<class Visitor>
int PNS_INDEX::Query( const SHAPE *aShape, int aMinDistance, Visitor &v)
{
int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v )
{
int total = 0;
for(int i = 0; i < MaxSubIndices; i++)
total += querySingle(i, aShape, aMinDistance, v);
for( int i = 0; i < MaxSubIndices; i++ )
total += querySingle( i, aShape, aMinDistance, v );
return total;
}
}
void PNS_INDEX::Clear()
{
for(int i = 0; i < MaxSubIndices; ++i)
for( int i = 0; i < MaxSubIndices; ++i )
{
ItemShapeIndex *idx = m_subIndices[i];
if(idx)
ItemShapeIndex* idx = m_subIndices[i];
if( idx )
delete idx;
m_subIndices[i] = NULL;
}
}
PNS_INDEX::~PNS_INDEX()
{
Clear();
}
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet ( int aNet )
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 &m_netMap[aNet];
}
#endif
......@@ -21,22 +21,25 @@
#include "pns_item.h"
#include "pns_line.h"
bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{
// same nets? no collision!
if( m_net == aOther->m_net )
return false;
// 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 GetShape()->Collide ( aOther->GetShape(), aClearance );
return GetShape()->Collide( aOther->GetShape(), aClearance );
// fixme: MTV
}
bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
return true;
......@@ -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.
if( aOther->m_kind == LINE )
{
const PNS_LINE *line = static_cast<const PNS_LINE *> (aOther);
if(line -> EndsWithVia())
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV );
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
if( line->EndsWithVia() )
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV,
aMTV );
}
return false;
}
const std::string PNS_ITEM::GetKindStr() const
{
switch(m_kind)
switch( m_kind )
{
case LINE: return "line";
case SEGMENT: return "segment";
case VIA: return "via";
case JOINT: return "joint";
case SOLID: return "solid";
default: return "unknown";
case LINE:
return "line";
case SEGMENT:
return "segment";
case VIA:
return "via";
case JOINT:
return "joint";
case SOLID:
return "solid";
default:
return "unknown";
}
}
PNS_ITEM::~PNS_ITEM()
{
}
......@@ -41,11 +41,11 @@ class PNS_NODE;
class PNS_ITEM
{
public:
static const int UnusedNet = INT_MAX;
///> Supported item types
enum PnsKind {
enum PnsKind
{
SOLID = 1,
LINE = 2,
JOINT = 4,
......@@ -54,7 +54,7 @@ public:
ANY = 0xff
};
PNS_ITEM(PnsKind aKind)
PNS_ITEM( PnsKind aKind )
{
m_net = UnusedNet;
m_movable = true;
......@@ -77,79 +77,82 @@ public:
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
/// path.
/// 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.
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();
};
PnsKind GetKind() const { return m_kind; }
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; }
const std::string GetKindStr() const;
///> Gets/Sets the corresponding parent object in the host application's model (pcbnew)
void SetParent(BOARD_ITEM *aParent) { m_parent = aParent; }
BOARD_ITEM *GetParent() const { return m_parent; }
void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; }
BOARD_ITEM* GetParent() const { return m_parent; }
///> Net accessors
int GetNet() const { return m_net; }
void SetNet(int aNet) { m_net = aNet; }
void SetNet( int aNet ) { m_net = aNet; }
///> Layers accessors
const PNS_LAYERSET& GetLayers() const { return m_layers; }
void SetLayers ( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; }
void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); }
void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; }
void SetLayer( int aLayer )
{
m_layers = PNS_LAYERSET( aLayer, aLayer );
}
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned.
void SetOwner (PNS_NODE *aOwner) { m_owner = aOwner; }
bool BelongsTo (PNS_NODE *aNode) const { return m_owner == aNode; }
PNS_NODE *GetOwner() const { return m_owner; }
void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; }
bool BelongsTo( PNS_NODE* aNode ) const { return m_owner == aNode; }
PNS_NODE* GetOwner() const { return m_owner; }
///> Sets the world that is used for collision resolution.
void SetWorld (PNS_NODE *aWorld) { m_world = aWorld; }
PNS_NODE *GetWorld() const { return m_world; }
void SetWorld( PNS_NODE* aWorld ) { m_world = aWorld; }
PNS_NODE* GetWorld() const { return m_world; }
///> Collision function. Checks if the item aOther is closer to us than
/// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the
/// collision if needed.
virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const;
/// aClearance and returns true if so. It can also calculate a minimum translation vector that
/// resolves the collision if needed.
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
///> A shortcut without MTV calculation
bool Collide( const PNS_ITEM *aOther, int aClearance ) const
bool Collide( const PNS_ITEM* aOther, int aClearance ) const
{
VECTOR2I dummy;
return Collide(aOther, aClearance, false, dummy);
return Collide( aOther, aClearance, false, dummy );
}
///> Returns the geometric shape of the item
virtual const SHAPE* GetShape() const {
virtual const SHAPE* GetShape() const
{
return NULL;
}
private:
bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const;
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
protected:
PnsKind m_kind;
BOARD_ITEM *m_parent;
PNS_NODE *m_world;
PNS_NODE *m_owner;
BOARD_ITEM* m_parent;
PNS_NODE* m_world;
PNS_NODE* m_owner;
PNS_LAYERSET m_layers;
bool m_movable;
int m_net;
};
#endif // __PNS_ITEM_H
#endif // __PNS_ITEM_Ha
......@@ -25,48 +25,57 @@
PNS_ITEMSET::PNS_ITEMSET()
{
}
PNS_ITEMSET::~PNS_ITEMSET()
{
}
PNS_ITEMSET& PNS_ITEMSET::FilterLayers ( int aStart, int aEnd )
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
{
ItemVector newItems;
PNS_LAYERSET l;
if(aEnd < 0)
l = PNS_LAYERSET(aStart);
if( aEnd < 0 )
l = PNS_LAYERSET( aStart );
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;
return *this;
}
PNS_ITEMSET& PNS_ITEMSET::FilterKinds ( int aKindMask )
PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
{
ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetKind() & aKindMask )
newItems.push_back(item);
BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetKind() & aKindMask )
newItems.push_back( item );
m_items = newItems;
return *this;
}
PNS_ITEMSET& PNS_ITEMSET::FilterNet ( int aNet )
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
{
ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetNet() == aNet)
newItems.push_back(item);
BOOST_FOREACH( PNS_ITEM * item, m_items )
if( item->GetNet() == aNet )
newItems.push_back( item );
m_items = newItems;
return *this;
}
......
......@@ -28,35 +28,36 @@
/**
* Class PNS_ITEMSET
*
* Holds a list of board items, that can be filtered against net, kinds, layers, etc.
* Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/
class PNS_ITEMSET
{
public:
typedef std::vector<PNS_ITEM *> ItemVector;
typedef std::vector<PNS_ITEM*> ItemVector;
PNS_ITEMSET();
~PNS_ITEMSET();
ItemVector& Items() { return m_items; }
PNS_ITEMSET& FilterLayers ( int aStart, int aEnd = -1 );
PNS_ITEMSET& FilterKinds ( int aKindMask );
PNS_ITEMSET& FilterNet ( int aNet );
PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 );
PNS_ITEMSET& FilterKinds( int aKindMask );
PNS_ITEMSET& FilterNet( int aNet );
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:
ItemVector m_items;
};
#endif
......@@ -32,35 +32,38 @@
/**
* Class PNS_JOINT
*
* Represents a 2D point on a given set of layers and belonging to a certain net,
* that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items.
* Represents a 2D point on a given set of layers and belonging to a certain
* net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between
* the items.
**/
class PNS_JOINT : public PNS_ITEM
{
public:
typedef std::vector<PNS_ITEM *> LinkedItems;
typedef std::vector<PNS_ITEM*> LinkedItems;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed
struct HashTag {
///> Joints are hashed by their position, layers and net.
/// Linked items are, obviously, not hashed
struct HashTag
{
VECTOR2I pos;
int net;
};
PNS_JOINT():
PNS_ITEM(JOINT) {}
PNS_JOINT() :
PNS_ITEM( JOINT ) {}
PNS_JOINT(const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1):
PNS_ITEM(JOINT)
PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet = -1 ) :
PNS_ITEM( JOINT )
{
m_tag.pos = aPos;
m_tag.net = aNet;
m_layers = aLayers;
}
PNS_JOINT(const PNS_JOINT& b):
PNS_ITEM(JOINT)
PNS_JOINT( const PNS_JOINT& b ) :
PNS_ITEM( JOINT )
{
m_layers = b.m_layers;
m_tag.pos = b.m_tag.pos;
......@@ -69,99 +72,111 @@ public:
m_layers = b.m_layers;
}
PNS_ITEM *Clone() const
PNS_ITEM* Clone() const
{
assert(false);
assert( false );
return NULL;
}
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer.
///> Returns true if the joint is a trivial line corner, connecting two
/// segments of the same net, on the same layer.
bool IsLineCorner() const
{
if(m_linkedItems.size() != 2)
if( m_linkedItems.size() != 2 )
return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || m_linkedItems[1]->GetKind() != SEGMENT )
if( m_linkedItems[0]->GetKind() != SEGMENT ||
m_linkedItems[1]->GetKind() != SEGMENT )
return false;
PNS_SEGMENT *seg1 = static_cast<PNS_SEGMENT *> (m_linkedItems[0]);
PNS_SEGMENT *seg2 = static_cast<PNS_SEGMENT *> (m_linkedItems[1]);
PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]);
PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]);
// joints between segments of different widths are not trivial.
return (seg1->GetWidth() == seg2->GetWidth());
return seg1->GetWidth() == seg2->GetWidth();
}
///> Links the joint to a given board item (when it's added to the PNS_NODE)
void Link ( PNS_ITEM *aItem )
void Link( PNS_ITEM* aItem )
{
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem);
if(f != m_linkedItems.end())
LinkedItems::iterator f = std::find( m_linkedItems.begin(),
m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() )
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)
///> 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);
if(f != m_linkedItems.end())
m_linkedItems.erase(f);
return (m_linkedItems.size() == 0);
LinkedItems::iterator f = std::find( m_linkedItems.begin(),
m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() )
m_linkedItems.erase( f );
return m_linkedItems.size() == 0;
}
///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
///> 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 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
const HashTag& GetTag() const { return m_tag; }
const VECTOR2I& GetPos() const { return m_tag.pos; }
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.
int LinkCount( int aMask = -1 ) const
{
int n = 0;
for(LinkedItems::const_iterator i = m_linkedItems.begin(); i!= m_linkedItems.end(); ++i)
for( LinkedItems::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i )
if( (*i)->GetKind() & aMask )
n++;
return n;
}
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;
}
void Merge( const PNS_JOINT& aJoint )
{
if(!Overlaps(aJoint))
if( !Overlaps( aJoint ) )
return;
m_layers.Merge (aJoint.m_layers);
m_layers.Merge( aJoint.m_layers );
// fixme: duplicate links (?)
for(LinkedItems::const_iterator i =aJoint.m_linkedItems.begin(); i!=aJoint.m_linkedItems.end();++i)
m_linkedItems.push_back(*i);
for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin();
i != aJoint.m_linkedItems.end(); ++i )
m_linkedItems.push_back( *i );
}
bool Overlaps(const PNS_JOINT& rhs) const
bool Overlaps( const PNS_JOINT& rhs ) const
{
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net && m_layers.Overlaps(rhs.m_layers);
return m_tag.pos == rhs.m_tag.pos &&
m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
}
private:
///> hash tag for unordered_multimap
HashTag m_tag;
......@@ -171,18 +186,22 @@ private:
// hash function & comparison operator for boost::unordered_map<>
inline bool operator==(PNS_JOINT::HashTag const& p1, PNS_JOINT::HashTag const& p2)
inline bool operator==( PNS_JOINT::HashTag const& p1,
PNS_JOINT::HashTag const& p2 )
{
return p1.pos == p2.pos && p1.net == p2.net;
}
inline std::size_t hash_value(PNS_JOINT::HashTag const& p)
inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
{
std::size_t seed = 0;
boost::hash_combine(seed, p.pos.x);
boost::hash_combine(seed, p.pos.y);
boost::hash_combine(seed, p.net);
boost::hash_combine( seed, p.pos.x );
boost::hash_combine( seed, p.pos.y );
boost::hash_combine( seed, p.net );
return seed;
}
#endif // __PNS_JOINT_H
......@@ -28,91 +28,93 @@
*
* Represents a contiguous set of PCB layers.
*/
class PNS_LAYERSET
{
public:
PNS_LAYERSET():
m_start(-1),
m_end(-1)
public:
PNS_LAYERSET() :
m_start( -1 ),
m_end( -1 )
{};
PNS_LAYERSET (int aStart, int aEnd)
PNS_LAYERSET( int aStart, int aEnd )
{
if(aStart > aEnd)
std::swap(aStart, aEnd);
if( aStart > aEnd )
std::swap( aStart, aEnd );
m_start = aStart;
m_end = aEnd;
}
PNS_LAYERSET (int aLayer)
PNS_LAYERSET( int aLayer )
{
m_start = m_end = aLayer;
}
PNS_LAYERSET(const PNS_LAYERSET &b) :
m_start(b.m_start),
m_end (b.m_end)
PNS_LAYERSET( const PNS_LAYERSET& b ) :
m_start( b.m_start ),
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_end = b.m_end;
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;
}
bool Overlaps ( const int aLayer ) const
bool Overlaps( const int aLayer ) const
{
return aLayer >= m_start && aLayer <= m_end;
}
bool IsMultilayer ( ) const
bool IsMultilayer() const
{
return m_start != m_end;
}
int Start() const {
int Start() const
{
return m_start;
}
int End() const {
int End() const
{
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_end = aOther.m_end;
return;
}
if(aOther.m_start < m_start)
if( aOther.m_start < m_start )
m_start = aOther.m_start;
if(aOther.m_end > m_end)
if( aOther.m_end > m_end )
m_end = aOther.m_end;
}
///> Shortcut for comparisons/overlap tests
static PNS_LAYERSET All()
{
return PNS_LAYERSET(0, 256);
return PNS_LAYERSET( 0, 256 );
}
private:
private:
int m_start;
int m_end;
};
#endif // __PNS_LAYERSET_H
This diff is collapsed.
......@@ -38,46 +38,48 @@ class PNS_VIA;
/**
* Class PNS_LINE
*
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,
* junctions between multiple traces or two traces different widths and combinations of these).
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on
* a via/pad/segment that belongs/begins them.
* Represents a track on a PCB, connecting two non-trivial joints (that is,
* vias, pads, junctions between multiple traces or two traces different widths
* and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
*
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends.
* PNS_LINEs can be either loose (consisting of segments that do not belong to
* any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends.
*
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff.
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/
class PNS_LINE : public PNS_ITEM
{
public:
typedef std::vector<PNS_SEGMENT *> LinkedSegments;
typedef std::vector<PNS_SEGMENT*> LinkedSegments;
PNS_LINE ():
PNS_ITEM(LINE)
PNS_LINE() :
PNS_ITEM( LINE )
{
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
};
PNS_LINE (int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine) :
PNS_ITEM(LINE)
PNS_LINE( int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine ) :
PNS_ITEM( LINE )
{
m_line = aLine;
m_width = aWidth;
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
SetLayer(aLayer);
SetLayer( aLayer );
}
PNS_LINE(const PNS_LINE& aOther) :
PNS_ITEM(aOther),
m_line(aOther.m_line),
m_width(aOther.m_width)
PNS_LINE( const PNS_LINE& aOther ) :
PNS_ITEM( aOther ),
m_line( aOther.m_line ),
m_width( aOther.m_width )
{
m_net = aOther.m_net;
m_movable = aOther.m_movable;
......@@ -94,10 +96,10 @@ public:
* copies properties (net, layers from a base line), and replaces the shape
* by aLine
**/
PNS_LINE(const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine) :
PNS_ITEM(aBase),
m_line(aLine),
m_width(aBase.m_width)
PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) :
PNS_ITEM( aBase ),
m_line( aLine ),
m_width( aBase.m_width )
{
m_net = aBase.m_net;
m_layers = aBase.m_layers;
......@@ -106,64 +108,68 @@ public:
m_affectedRangeStart = -1;
}
~PNS_LINE ()
~PNS_LINE()
{
if(m_segmentRefs)
if( 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.)
PNS_LINE *CloneProperties() const ;
///> clones the line without cloning the shape
///> (just the properties - net, width, layers, etc.)
PNS_LINE* CloneProperties() const;
int GetLayer() const { return GetLayers().Start(); }
///> 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; }
SHAPE_LINE_CHAIN& GetLine() { return m_line; }
const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
///> Width accessors
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
void LinkSegment(PNS_SEGMENT *aSeg)
void LinkSegment( PNS_SEGMENT* aSeg )
{
if(!m_segmentRefs)
m_segmentRefs = new std::vector<PNS_SEGMENT *> ();
m_segmentRefs->push_back(aSeg);
if( !m_segmentRefs )
m_segmentRefs = new std::vector<PNS_SEGMENT*> ();
m_segmentRefs->push_back( aSeg );
}
///> Returns a list of segments from the owning node that constitute this line (or NULL if
///> the line is loose)
///> Returns a list of segments from the owning node that constitute this
///> line (or NULL if the line is loose)
LinkedSegments* GetLinkedSegments()
{
return m_segmentRefs;
}
bool ContainsSegment (PNS_SEGMENT *aSeg) const
bool ContainsSegment( PNS_SEGMENT* aSeg ) const
{
if (!m_segmentRefs)
if( !m_segmentRefs )
return false;
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end();
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(),
aSeg ) != m_segmentRefs->end();
}
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE *aNode ) const;
///> Returns this line, but clipped to the nearest obstacle
///> along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const;
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
bool MergeObtuseSegments();
bool MergeSegments();
///> 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
///> aWalkaroundPath = path around the obstacle
///> aPostPath = past from obstacle till the end
......@@ -179,13 +185,16 @@ public:
bool aCw ) const;
bool Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const;
bool Walkaround( SHAPE_LINE_CHAIN obstacle,
SHAPE_LINE_CHAIN& pre,
SHAPE_LINE_CHAIN& walk,
SHAPE_LINE_CHAIN& post,
bool cw ) const;
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath,
bool aCw ) const;
bool Is45Degree();
///> Prints out all linked segments
......@@ -193,34 +202,37 @@ public:
bool EndsWithVia() const { return m_hasVia; }
void AppendVia ( const PNS_VIA &aVia ) {
void AppendVia( const PNS_VIA& aVia )
{
m_hasVia = true;
m_via = aVia;
m_via.SetNet ( m_net ) ;
m_via.SetNet( m_net );
}
void RemoveVia() { m_hasVia = false; }
const PNS_VIA& GetVia() const { return m_via; }
void SetAffectedRange ( int aStart, int aEnd )
void SetAffectedRange( int aStart, int aEnd )
{
m_affectedRangeStart = aStart;
m_affectedRangeEnd = aEnd;
}
void ClearAffectedRange ( )
void ClearAffectedRange()
{
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;
aEnd = m_affectedRangeEnd;
return true;
} else {
}
else
{
aStart = 0;
aEnd = m_line.PointCount();
return false;
......@@ -228,8 +240,9 @@ public:
}
private:
bool onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const;
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const;
bool 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;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments* m_segmentRefs;
......@@ -238,6 +251,7 @@ private:
SHAPE_LINE_CHAIN m_line;
int m_width;
///> Via at the end and a flag indicating if it's enabled.
PNS_VIA m_via;
bool m_hasVia;
......@@ -246,6 +260,5 @@ private:
int m_affectedRangeEnd;
};
#endif // __PNS_LINE_H
This diff is collapsed.
......@@ -39,17 +39,18 @@ class PNS_ROUTER_BASE;
/**
* Class PNS_LINE_PLACER
*
* Interactively routes a single track. Runs shove and walkaround algorithms when needed.
* Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/
class PNS_LINE_PLACER
{
public:
PNS_LINE_PLACER( PNS_NODE *aWorld );
public:
PNS_LINE_PLACER( PNS_NODE* aWorld );
~PNS_LINE_PLACER();
///> 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_viaDrill = aDrill;
......@@ -57,100 +58,198 @@ class PNS_LINE_PLACER
}
///> 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
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; }
///> Returns the "tail" of the line being placed the part that has been fixed already (follow mouse mode only)
///> Returns the "tail" of the line being placed the part that has been
///> fixed already (follow mouse mode only)
const PNS_LINE& GetTail() const { return m_tail; }
///> Returns the whole routed line
const PNS_LINE GetTrace() const;
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions.
///> Returns the current end of the line being placed. It may not be equal
///> to the cursor position due to collisions.
const VECTOR2I& CurrentEnd() const
{
if(m_head.GetCLine().PointCount() > 0)
return m_head.GetCLine().CPoint(-1);
else if(m_tail.GetCLine().PointCount() > 0)
return m_tail.GetCLine().CPoint(-1);
if( m_head.GetCLine().PointCount() > 0 )
return m_head.GetCLine().CPoint( -1 );
else if( m_tail.GetCLine().PointCount() > 0 )
return m_tail.GetCLine().CPoint( -1 );
else
return m_p_start;
}
///> Returns all items in the world that have been affected by the routing operation. Used
/// to update data structures of the host application
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded);
///> Returns all items in the world that have been affected by the routing
///> operation. Used to update data structures of the host application
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
PNS_NODE::ItemVector& aAdded );
///> Toggles the current posture (straight/diagonal) of the trace head.
void FlipPosture();
///> Returns the most recent world state
PNS_NODE *GetCurrentNode() const;
private:
PNS_NODE* GetCurrentNode() const;
private:
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();
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards
* wrs to the current tail direction.
* @return true if the line has been changed.
*/
bool handlePullback();
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
bool mergeHead();
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();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool optimizeTailHeadTransition();
bool routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround = true);
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.)
PNS_MODE m_mode;
///> follow mouse trail by attaching new segments to the head as the cursor moves
///> follow mouse trail by attaching new segments to the head
///> as the cursor moves
bool m_follow_mouse;
///> mouse smoothing active
bool m_smooth_mouse;
///> mouse smoothing step (in world units)
int m_smoothing_step;
///> current routing direction
DIRECTION_45 m_direction;
///> routing direction for new traces
DIRECTION_45 m_initial_direction;
///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination
PNS_LINE m_head;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE m_tail;
///> current algorithm iteration
int m_iteration;
///> pointer to world to search colliding items
PNS_NODE *m_world;
PNS_NODE* m_world;
///> current routing start point (end of tail, beginning of head)
VECTOR2I m_p_start;
///> The shove engine
PNS_SHOVE *m_shove;
PNS_SHOVE* m_shove;
///> Current world state
PNS_NODE *m_currentNode;
PNS_NODE* m_currentNode;
///> Are we placing a via?
bool m_placingVia;
///> current via diameter
int m_viaDiameter;
///> current via drill
int m_viaDrill;
///> walkaround algorithm iteration limit
int m_walkaroundIterationLimit;
///> smart pads optimizer enabled.
bool m_smartPads;
};
#endif // __PNS_LINE_PLACER_H
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 @@
#define __PNS_ROUTER_SETTINGS
///> Routing modes
enum PNS_MODE {
enum PNS_MODE
{
RM_Ignore = 0, ///> Ignore collisions
RM_Shove, ///> Only shove
RM_Walkaround, ///> Only walkaround
......@@ -31,7 +32,7 @@ enum PNS_MODE {
class PNS_ROUTING_SETTINGS
{
public:
public:
PNS_MODE m_routingMode;
bool m_removeLoops;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -29,24 +29,26 @@
#include "pns_item.h"
class PNS_SOLID : public PNS_ITEM {
class PNS_SOLID : public PNS_ITEM
{
public:
PNS_SOLID() : PNS_ITEM(SOLID)
PNS_SOLID() : PNS_ITEM( SOLID )
{
m_movable = false;
m_shape = NULL;
}
PNS_ITEM *Clone() const;
PNS_ITEM* Clone() const;
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;
m_shape = shape;
}
......@@ -61,7 +63,6 @@ public:
}
private:
VECTOR2I m_center;
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