Commit 936e0be0 authored by Maciej Suminski's avatar Maciej Suminski

Uncrustified the push&shove source, fixed some warnings.

parents 87b3f2e4 5598acb6
......@@ -362,7 +362,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
return;
#ifdef CACHED_CONTAINER_TEST > 0
#if CACHED_CONTAINER_TEST > 0
prof_counter totalTime;
prof_start( &totalTime, false );
#endif
......@@ -406,7 +406,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
// Add the last one
m_freeChunks.insert( std::make_pair( size, offset ) );
#ifdef CACHED_CONTAINER_TEST > 0
#if CACHED_CONTAINER_TEST > 0
prof_end( &totalTime );
wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 );
......
......@@ -69,7 +69,7 @@ void VIEW_ITEM::ViewRelease()
void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const
{
int* layersPtr = aLayers;
for( int i = 0; i < m_layers.size(); ++i )
for( unsigned int i = 0; i < m_layers.size(); ++i )
{
if( m_layers[i] )
*layersPtr++ = i;
......
include_directories(BEFORE ${INC_BEFORE})
include_directories( BEFORE ${INC_BEFORE} )
include_directories(
./
......@@ -7,9 +7,9 @@ include_directories(
../../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.
This diff is collapsed.
This diff is collapsed.
......@@ -24,10 +24,10 @@
#include <math/vector2d.h>
#include <geometry/shape_line_chain.h>
/** Various utility functions */
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, int aChamfer);
const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
int aClearance, int aChamfer );
#endif // __PNS_UTILS_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
You'll see the P&S router sources here, but just not right now.
We are still dealing with some non-technical issues that should be solved by the next week.
Tom
\ No newline at end of file
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