Uncrustified the push&shove source, fixed some warnings.

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

View File

@ -362,7 +362,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged if( m_freeChunks.size() <= 1 ) // There are no chunks that can be merged
return; return;
#ifdef CACHED_CONTAINER_TEST > 0 #if CACHED_CONTAINER_TEST > 0
prof_counter totalTime; prof_counter totalTime;
prof_start( &totalTime, false ); prof_start( &totalTime, false );
#endif #endif
@ -406,7 +406,7 @@ void CACHED_CONTAINER::mergeFreeChunks()
// Add the last one // Add the last one
m_freeChunks.insert( std::make_pair( size, offset ) ); m_freeChunks.insert( std::make_pair( size, offset ) );
#ifdef CACHED_CONTAINER_TEST > 0 #if CACHED_CONTAINER_TEST > 0
prof_end( &totalTime ); prof_end( &totalTime );
wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 ); wxLogDebug( wxT( "Merged free chunks / %.1f ms" ), (double) totalTime.value / 1000.0 );

View File

@ -69,7 +69,7 @@ void VIEW_ITEM::ViewRelease()
void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const void VIEW_ITEM::getLayers( int* aLayers, int& aCount ) const
{ {
int* layersPtr = aLayers; 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] ) if( m_layers[i] )
*layersPtr++ = i; *layersPtr++ = i;

View File

@ -1,50 +1,51 @@
include_directories(BEFORE ${INC_BEFORE}) include_directories( BEFORE ${INC_BEFORE} )
include_directories( include_directories(
./ ./
../ ../
../../include ../../include
../../pcbnew ../../pcbnew
../../polygon ../../polygon
${INC_AFTER} ${INC_AFTER}
) )
set(PCBNEW_PNS_SRCS set( PCBNEW_PNS_SRCS
direction.h direction.h
pns_via.h pns_via.h
pns_routing_settings.h pns_routing_settings.h
pns_shove.cpp pns_shove.cpp
pns_line.cpp pns_line.cpp
pns_utils.h pns_utils.h
pns_layerset.h pns_layerset.h
trace.h trace.h
pns_line.h pns_line.h
pns_walkaround.cpp pns_walkaround.cpp
pns_node.h pns_node.h
pns_line_placer.cpp pns_line_placer.cpp
pns_utils.cpp pns_utils.cpp
pns_solid.h pns_solid.h
pns_item.cpp pns_item.cpp
pns_via.cpp pns_via.cpp
pns_node.cpp pns_node.cpp
pns_solid.cpp pns_solid.cpp
pns_line_placer.h pns_line_placer.h
pns_optimizer.h pns_optimizer.h
pns_walkaround.h pns_walkaround.h
pns_shove.h pns_shove.h
pns_router.h pns_router.h
pns_router.cpp pns_router.cpp
pns_index.h pns_index.h
pns_item.h pns_item.h
pns_optimizer.cpp pns_optimizer.cpp
pns_joint.h pns_joint.h
pns_segment.h pns_segment.h
pns_itemset.h pns_itemset.h
pns_itemset.cpp pns_itemset.cpp
router_tool.cpp router_tool.cpp
router_tool.h router_tool.h
router_preview_item.cpp router_preview_item.cpp
router_preview_item.h router_preview_item.h
) )
add_library( pnsrouter STATIC ${PCBNEW_PNS_SRCS} )
add_library(pnsrouter STATIC ${PCBNEW_PNS_SRCS})

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -31,265 +31,302 @@
class DIRECTION_45 class DIRECTION_45
{ {
public: public:
/**
* Enum Directions
* 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 {
N = 0,
NE = 1,
E = 2,
SE = 3,
S = 4,
SW = 5,
W = 6,
NW = 7,
UNDEFINED = -1
};
/** /**
* Enum AngleType * Enum Directions
* Represents kind of angle formed by vectors heading in two DIRECTION_45s. * 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 AngleType { */
ANG_OBTUSE = 0x1, enum Directions
ANG_RIGHT = 0x2, {
ANG_ACUTE = 0x4, N = 0,
ANG_STRAIGHT = 0x8, NE = 1,
ANG_HALF_FULL = 0x10, E = 2,
ANG_UNDEFINED = 0x20 SE = 3,
}; S = 4,
SW = 5,
W = 6,
NW = 7,
UNDEFINED = -1
};
DIRECTION_45(Directions aDir = UNDEFINED): m_dir(aDir) {}; /**
* Enum AngleType
/** * Represents kind of angle formed by vectors heading in two DIRECTION_45s.
* Constructor */
* @param aVec vector, whose direction will be translated into a DIRECTION_45. enum AngleType
*/ {
DIRECTION_45(const VECTOR2I& aVec) ANG_OBTUSE = 0x01,
{ ANG_RIGHT = 0x02,
construct(aVec); ANG_ACUTE = 0x04,
} ANG_STRAIGHT = 0x08,
ANG_HALF_FULL = 0x10,
ANG_UNDEFINED = 0x20
};
/** DIRECTION_45( Directions aDir = UNDEFINED ) : m_dir( aDir ) {};
* Constructor
* @param aSeg segment, whose direction will be translated into a DIRECTION_45.
*/
DIRECTION_45(const SEG& aSeg)
{
construct( aSeg.b - aSeg.a );
}
/** /**
* Function Format() * Constructor
* Formats the direction in a human readable word. * @param aVec vector, whose direction will be translated into a DIRECTION_45.
* @return name of the direction */
*/ DIRECTION_45( const VECTOR2I& aVec )
const std::string Format() const {
{ construct( aVec );
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>";
}
}
/**
* Function Opposite()
* Returns a direction opposite (180 degree) to (this)
* @return opposite direction
*/
DIRECTION_45 Opposite() const
{
if(m_dir == UNDEFINED)
return UNDEFINED;
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE } ;
return OppositeMap[m_dir];
}
/** /**
* Function Angle() * Constructor
* Returns the type of angle between directions (this) and aOther. * @param aSeg segment, whose direction will be translated into a DIRECTION_45.
* @param aOther direction to compare angle with */
*/ DIRECTION_45( const SEG& aSeg )
AngleType Angle(const DIRECTION_45& aOther) const {
{ construct( aSeg.b - aSeg.a );
if(m_dir == UNDEFINED || aOther.m_dir == UNDEFINED) }
return ANG_UNDEFINED;
int d = std::abs(m_dir - aOther.m_dir); /**
* Function Format()
* Formats the direction in a human readable word.
* @return name of the direction
*/
const std::string Format() const
{
switch( m_dir )
{
case N:
return "north";
if(d == 1 || d == 7) case NE:
return ANG_OBTUSE; return "north-east";
else if(d == 2 || d == 6)
return ANG_RIGHT;
else if(d == 3 || d == 5)
return ANG_ACUTE;
else if(d == 4)
return ANG_HALF_FULL;
else
return ANG_STRAIGHT;
}
/** case E:
* Function IsObtuse() return "east";
* @return true, when (this) forms an obtuse angle with aOther
*/
bool IsObtuse(const DIRECTION_45& aOther) const
{
return Angle(aOther) == ANG_OBTUSE;
}
/** case SE:
* Function IsDiagonal() return "south-east";
* Returns true if the direction is diagonal (e.g. North-West, South-East, etc)
* @return true, when diagonal.
*/
bool IsDiagonal() const
{
return (m_dir % 2) == 1;
}
/**
* Function BuildInitialTrace()
*
* Builds a 2-segment line chain between points aP0 and aP1 and following 45-degree routing
* regime. If aStartDiagonal is true, the trace starts with a diagonal segment.
* @param aP0 starting point
* @param aP1 ending point
* @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
{
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; case S:
return "south";
// we are more horizontal than vertical?
if(w > h)
{
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
}
bool start_diagonal; case SW:
return "south-west";
if(m_dir == UNDEFINED) case W:
start_diagonal = aStartDiagonal; return "west";
else
start_diagonal = IsDiagonal();
SHAPE_LINE_CHAIN pl; case NW:
return "north-west";
pl.Append(aP0); case UNDEFINED:
if (start_diagonal) return "undefined";
pl.Append(aP0 + mp1);
else
pl.Append(aP0 + mp0);
pl.Append(aP1);
pl.Simplify();
return pl;
};
bool operator==(const DIRECTION_45& aOther) const default:
{ return "<Error>";
return aOther.m_dir == m_dir; }
} }
bool operator!=(const DIRECTION_45& aOther) const /**
{ * Function Opposite()
return aOther.m_dir != m_dir; * Returns a direction opposite (180 degree) to (this)
} * @return opposite direction
*/
DIRECTION_45 Opposite() const
{
if( m_dir == UNDEFINED )
return UNDEFINED;
const DIRECTION_45 Right() const const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE };
{ return OppositeMap[m_dir];
DIRECTION_45 r; }
r.m_dir = (Directions) (m_dir + 1);
if(r.m_dir == NW) /**
r.m_dir = N; * Function Angle()
return r; * Returns the type of angle between directions (this) and aOther.
} * @param aOther direction to compare angle with
*/
AngleType Angle( const DIRECTION_45& aOther ) const
{
if( m_dir == UNDEFINED || aOther.m_dir == UNDEFINED )
return ANG_UNDEFINED;
int d = std::abs( m_dir - aOther.m_dir );
if( d == 1 || d == 7 )
return ANG_OBTUSE;
else if( d == 2 || d == 6 )
return ANG_RIGHT;
else if( d == 3 || d == 5 )
return ANG_ACUTE;
else if( d == 4 )
return ANG_HALF_FULL;
else
return ANG_STRAIGHT;
}
/**
* Function IsObtuse()
* @return true, when (this) forms an obtuse angle with aOther
*/
bool IsObtuse( const DIRECTION_45& aOther ) const
{
return Angle( aOther ) == ANG_OBTUSE;
}
/**
* Function IsDiagonal()
* Returns true if the direction is diagonal (e.g. North-West, South-East, etc)
* @return true, when diagonal.
*/
bool IsDiagonal() const
{
return ( m_dir % 2 ) == 1;
}
/**
* Function BuildInitialTrace()
*
* Builds a 2-segment line chain between points aP0 and aP1 and following 45-degree routing
* regime. If aStartDiagonal is true, the trace starts with a diagonal segment.
* @param aP0 starting point
* @param aP1 ending point
* @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
{
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 )
{
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
}
bool start_diagonal;
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 );
else
pl.Append( aP0 + mp0 );
pl.Append( aP1 );
pl.Simplify();
return pl;
};
bool operator==( const DIRECTION_45& aOther ) const
{
return aOther.m_dir == m_dir;
}
bool operator!=( const DIRECTION_45& aOther ) const
{
return aOther.m_dir != m_dir;
}
const DIRECTION_45 Right() const
{
DIRECTION_45 r;
r.m_dir = (Directions) (m_dir + 1);
if( r.m_dir == NW )
r.m_dir = N;
return r;
}
private: private:
template <typename T> int sign(T val) const { template <typename T>
return (T(0) < val) - (val < T(0)); int sign( T val ) const
} {
return (T( 0 ) < val) - ( val < T( 0 ) );
}
/** /**
* Function construct() * Function construct()
* Calculates the direction from a vector. If the vector's angle is not a multiple of 45 * Calculates the direction from a vector. If the vector's angle is not a multiple of 45
* degrees, the direction is rounded to the nearest octant. * degrees, the direction is rounded to the nearest octant.
* @param aVec our vector * @param aVec our vector
*/ */
void construct(const VECTOR2I& aVec) void construct( const VECTOR2I& aVec )
{ {
m_dir = UNDEFINED; m_dir = UNDEFINED;
if(aVec.x == 0 && aVec.y == 0)
return;
double mag = 360.0 - (180.0 / M_PI * atan2 ((double) aVec.y, (double) aVec.x )) + 90.0; if( aVec.x == 0 && aVec.y == 0 )
if (mag >= 360.0) return;
mag -= 360.0;
if(mag < 0.0)
mag += 360.0;
m_dir = (Directions) ((mag + 22.5) / 45.0);
if(m_dir >= 8) double mag = 360.0 - ( 180.0 / M_PI * atan2( (double) aVec.y, (double) aVec.x ) ) + 90.0;
m_dir = (Directions) (m_dir - 8);
if(m_dir < 0)
m_dir = (Directions) (m_dir + 8);
return ; if( mag >= 360.0 )
if(aVec.y < 0) mag -= 360.0;
{
if(aVec.x > 0)
m_dir = NE;
else if(aVec.x < 0)
m_dir = NW;
else
m_dir = N;
}
else if(aVec.y == 0)
{
if(aVec.x > 0)
m_dir = E;
else
m_dir = W;
}
else // aVec.y>0
{
if(aVec.x > 0)
m_dir = SE;
else if(aVec.x < 0)
m_dir = SW;
else
m_dir = S;
}
}
Directions m_dir; ///> our actual direction if( mag < 0.0 )
}; mag += 360.0;
m_dir = (Directions)( ( mag + 22.5 ) / 45.0 );
if( m_dir >= 8 )
m_dir = (Directions)( m_dir - 8 );
if( m_dir < 0 )
m_dir = (Directions)( m_dir + 8 );
return;
if( aVec.y < 0 )
{
if( aVec.x > 0 )
m_dir = NE;
else if( aVec.x < 0 )
m_dir = NW;
else
m_dir = N;
}
else if( aVec.y == 0 )
{
if( aVec.x > 0 )
m_dir = E;
else
m_dir = W;
}
else // aVec.y>0
{
if( aVec.x > 0 )
m_dir = SE;
else if( aVec.x < 0 )
m_dir = SW;
else
m_dir = S;
}
}
Directions m_dir; ///> our actual direction
};
#endif // __DIRECTION_H
#endif // __DIRECTION_H

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -37,205 +37,227 @@
* overlap and improving search time. * overlap and improving search time.
**/ **/
class PNS_INDEX { class PNS_INDEX
{
public: public:
typedef std::list<PNS_ITEM*> NetItemsList;
typedef std::list<PNS_ITEM *> NetItemsList; typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex;
typedef SHAPE_INDEX<PNS_ITEM *> ItemShapeIndex; typedef boost::unordered_set<PNS_ITEM*> ItemSet;
typedef boost::unordered_set<PNS_ITEM *> ItemSet;
PNS_INDEX(); PNS_INDEX();
~PNS_INDEX(); ~PNS_INDEX();
void Add( PNS_ITEM *aItem ); void Add( PNS_ITEM* aItem );
void Remove ( PNS_ITEM *aItem ); void Remove( PNS_ITEM* aItem );
void Replace ( PNS_ITEM *aOldItem, PNS_ITEM *aNewItem ); void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
template<class Visitor> template<class Visitor>
int Query( const PNS_ITEM *aItem, int aMinDistance, Visitor &v); int Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v );
template<class Visitor>
int Query( const SHAPE *aShape, int aMinDistance, Visitor &v);
void Clear(); template<class Visitor>
int Query( const SHAPE* aShape, int aMinDistance, Visitor& v );
NetItemsList* GetItemsForNet ( int aNet ) ; void Clear();
ItemSet::iterator begin() { return m_allItems.begin(); } NetItemsList* GetItemsForNet( int aNet );
ItemSet::iterator end() { return m_allItems.end(); }
bool Contains ( PNS_ITEM *aItem ) const { ItemSet::iterator begin() { return m_allItems.begin(); }
return m_allItems.find(aItem) != m_allItems.end(); ItemSet::iterator end() { return m_allItems.end(); }
}
int Size() const { return m_allItems.size(); } bool Contains( PNS_ITEM* aItem ) const
{
return m_allItems.find( aItem ) != m_allItems.end();
}
int Size() const { return m_allItems.size(); }
private: private:
static const int MaxSubIndices = 64;
static const int SI_Multilayer = 2;
static const int SI_SegDiagonal = 0;
static const int SI_SegStraight = 1;
static const int SI_Traces = 3;
static const int SI_PadsTop = 0;
static const int SI_PadsBottom = 1;
static const int MaxSubIndices = 64; template <class Visitor>
static const int SI_Multilayer = 2; int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v );
static const int SI_SegDiagonal = 0;
static const int SI_SegStraight = 1;
static const int SI_Traces = 3;
static const int SI_PadsTop = 0;
static const int SI_PadsBottom = 1;
template<class Visitor> ItemShapeIndex* getSubindex( const PNS_ITEM* aItem );
int querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v);
ItemShapeIndex *getSubindex( const PNS_ITEM *aItem ); ItemShapeIndex* m_subIndices[MaxSubIndices];
std::map<int, NetItemsList> m_netMap;
ItemShapeIndex *m_subIndices[ MaxSubIndices ]; ItemSet m_allItems;
std::map<int, NetItemsList> m_netMap;
ItemSet m_allItems;
}; };
PNS_INDEX::PNS_INDEX() PNS_INDEX::PNS_INDEX()
{ {
memset(m_subIndices, 0, sizeof(m_subIndices)); memset( m_subIndices, 0, sizeof( m_subIndices ) );
} }
PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
{ {
int idx_n = -1; int idx_n = -1;
const PNS_LAYERSET l = aItem->GetLayers(); const PNS_LAYERSET l = aItem->GetLayers();
switch(aItem->GetKind())
{
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
idx_n = SI_PadsTop;
else if (l.Start() == 15)
idx_n = SI_PadsBottom;
break;
}
case PNS_ITEM::SEGMENT:
case PNS_ITEM::LINE:
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
break;
default:
break;
}
assert(idx_n >= 0 && idx_n < MaxSubIndices);
if(!m_subIndices[idx_n]) switch( aItem->GetKind() )
m_subIndices[idx_n] = new ItemShapeIndex; {
case PNS_ITEM::VIA:
idx_n = SI_Multilayer;
break;
return m_subIndices[idx_n]; case PNS_ITEM::SOLID:
{
if( l.IsMultilayer() )
idx_n = SI_Multilayer;
else if( l.Start() == 0 ) // fixme: use kicad layer codes
idx_n = SI_PadsTop;
else if( l.Start() == 15 )
idx_n = SI_PadsBottom;
break;
}
case PNS_ITEM::SEGMENT:
case PNS_ITEM::LINE:
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
break;
default:
break;
}
assert( idx_n >= 0 && idx_n < MaxSubIndices );
if( !m_subIndices[idx_n] )
m_subIndices[idx_n] = new ItemShapeIndex;
return m_subIndices[idx_n];
} }
void PNS_INDEX::Add( PNS_ITEM *aItem )
void PNS_INDEX::Add( PNS_ITEM* aItem )
{ {
ItemShapeIndex *idx = getSubindex(aItem); ItemShapeIndex* idx = getSubindex( aItem );
idx->Add(aItem); idx->Add( aItem );
m_allItems.insert(aItem); m_allItems.insert( aItem );
int net = aItem->GetNet(); int net = aItem->GetNet();
if(net >= 0)
{ if( net >= 0 )
m_netMap[net].push_back(aItem); {
} m_netMap[net].push_back( aItem );
}
} }
void PNS_INDEX::Remove( PNS_ITEM *aItem )
void PNS_INDEX::Remove( PNS_ITEM* aItem )
{ {
ItemShapeIndex *idx = getSubindex(aItem); ItemShapeIndex* idx = getSubindex( aItem );
idx->Remove(aItem);
m_allItems.erase (aItem);
int net = aItem->GetNet(); idx->Remove( aItem );
m_allItems.erase( aItem );
if(net >= 0 && m_netMap.find(net) != m_netMap.end())
m_netMap[net].remove(aItem); int net = aItem->GetNet();
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); Remove( aOldItem );
Add(aNewItem); Add( aNewItem );
} }
template<class Visitor> template<class Visitor>
int PNS_INDEX::querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v) int PNS_INDEX::querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& v )
{ {
if(!m_subIndices[index]) if( !m_subIndices[index] )
return 0; return 0;
return m_subIndices[index] -> Query(aShape, aMinDistance, v, false);
} return m_subIndices[index]->Query( aShape, aMinDistance, v, false );
}
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const PNS_ITEM *aItem, int aMinDistance, Visitor &v) int PNS_INDEX::Query( const PNS_ITEM* aItem, int aMinDistance, Visitor& v )
{ {
const SHAPE *shape = aItem->GetShape(); const SHAPE* shape = aItem->GetShape();
int total = 0; int total = 0;
total += querySingle(SI_Multilayer, shape, aMinDistance, v);
const PNS_LAYERSET layers = aItem->GetLayers(); total += querySingle( SI_Multilayer, shape, aMinDistance, v );
if(layers.IsMultilayer())
{
total += querySingle(SI_PadsTop, shape, aMinDistance, v);
total += querySingle(SI_PadsBottom, shape, aMinDistance, v);
const PNS_LAYERSET layers = aItem->GetLayers();
for(int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v);
} else { if( layers.IsMultilayer() )
int l = layers.Start(); {
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
if(l == 0) for( int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle(SI_PadsTop, shape, aMinDistance, v); total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v );
else if(l == 15) }
total += querySingle(SI_PadsBottom, shape, aMinDistance, v); else
total += querySingle ( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v); {
} int l = layers.Start();
if( l == 0 )
total += querySingle( SI_PadsTop, shape, aMinDistance, v );
else if( l == 15 )
total += querySingle( SI_PadsBottom, shape, aMinDistance, v );
total += querySingle( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v );
}
return total;
}
return total;
}
template<class Visitor> template<class Visitor>
int PNS_INDEX::Query( const SHAPE *aShape, int aMinDistance, Visitor &v) int PNS_INDEX::Query( const SHAPE* aShape, int aMinDistance, Visitor& v )
{ {
int total = 0; int total = 0;
for(int i = 0; i < MaxSubIndices; i++)
total += querySingle(i, aShape, aMinDistance, v); for( int i = 0; i < MaxSubIndices; i++ )
return total; total += querySingle( i, aShape, aMinDistance, v );
}
return total;
}
void PNS_INDEX::Clear() void PNS_INDEX::Clear()
{ {
for(int i = 0; i < MaxSubIndices; ++i) for( int i = 0; i < MaxSubIndices; ++i )
{ {
ItemShapeIndex *idx = m_subIndices[i]; ItemShapeIndex* idx = m_subIndices[i];
if(idx)
delete idx; if( idx )
m_subIndices[i] = NULL; delete idx;
}
m_subIndices[i] = NULL;
}
} }
PNS_INDEX::~PNS_INDEX() PNS_INDEX::~PNS_INDEX()
{ {
Clear(); Clear();
} }
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet ( int aNet )
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet )
{ {
if(m_netMap.find(aNet) == m_netMap.end()) if( m_netMap.find( aNet ) == m_netMap.end() )
return NULL; return NULL;
return &m_netMap[aNet];
return &m_netMap[aNet];
} }
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -21,52 +21,69 @@
#include "pns_item.h" #include "pns_item.h"
#include "pns_line.h" #include "pns_line.h"
bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{ {
// same nets? no collision! // same nets? no collision!
if( m_net == aOther->m_net ) if( m_net == aOther->m_net )
return false; return false;
// check if we are not on completely different layers first // check if we are not on completely different layers first
if (!m_layers.Overlaps (aOther->m_layers)) if( !m_layers.Overlaps( aOther->m_layers ) )
return false; return false;
return GetShape()->Collide ( aOther->GetShape(), aClearance ); return GetShape()->Collide( aOther->GetShape(), aClearance );
// fixme: MTV // fixme: MTV
} }
bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const
{ {
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) ) if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
return true; return true;
// special case for "head" line with a via attached at the end. // special case for "head" line with a via attached at the end.
if( aOther->m_kind == LINE ) if( aOther->m_kind == LINE )
{ {
const PNS_LINE *line = static_cast<const PNS_LINE *> (aOther); const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
if(line -> EndsWithVia())
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV );
}
return false; if( line->EndsWithVia() )
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV,
aMTV );
}
return false;
} }
const std::string PNS_ITEM::GetKindStr() const const std::string PNS_ITEM::GetKindStr() const
{ {
switch(m_kind) switch( m_kind )
{ {
case LINE: return "line"; case LINE:
case SEGMENT: return "segment"; return "line";
case VIA: return "via";
case JOINT: return "joint"; case SEGMENT:
case SOLID: return "solid"; return "segment";
default: return "unknown";
} case VIA:
return "via";
case JOINT:
return "joint";
case SOLID:
return "solid";
default:
return "unknown";
}
} }
PNS_ITEM::~PNS_ITEM() PNS_ITEM::~PNS_ITEM()
{ {
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -37,119 +37,122 @@ class PNS_NODE;
* Base class for PNS router board items. Implements the shared properties of all PCB items - * Base class for PNS router board items. Implements the shared properties of all PCB items -
* net, spanned layers, geometric shape & refererence to owning model. * net, spanned layers, geometric shape & refererence to owning model.
*/ */
class PNS_ITEM class PNS_ITEM
{ {
public: public:
static const int UnusedNet = INT_MAX;
static const int UnusedNet = INT_MAX; ///> Supported item types
enum PnsKind
{
SOLID = 1,
LINE = 2,
JOINT = 4,
SEGMENT = 8,
VIA = 16,
ANY = 0xff
};
///> Supported item types PNS_ITEM( PnsKind aKind )
enum PnsKind { {
SOLID = 1, m_net = UnusedNet;
LINE = 2, m_movable = true;
JOINT = 4, m_kind = aKind;
SEGMENT = 8, m_parent = NULL;
VIA = 16, m_world = NULL;
ANY = 0xff m_owner = NULL;
}; }
PNS_ITEM(PnsKind aKind) PNS_ITEM( const PNS_ITEM& aOther )
{ {
m_net = UnusedNet; m_layers = aOther.m_layers;
m_movable = true; m_net = aOther.m_net;
m_kind = aKind; m_movable = aOther.m_movable;
m_parent = NULL; m_kind = aOther.m_kind;
m_world = NULL; m_world = aOther.m_world;
m_owner = NULL; m_parent = aOther.m_parent;
} m_owner = NULL;
}
PNS_ITEM( const PNS_ITEM& aOther ) virtual ~PNS_ITEM();
{
m_layers = aOther.m_layers;
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_kind = aOther.m_kind;
m_world = aOther.m_world;
m_parent = aOther.m_parent;
m_owner = NULL;
}
virtual ~PNS_ITEM(); virtual PNS_ITEM* Clone() const = 0;
virtual PNS_ITEM *Clone() const = 0;
///> Returns a convex polygon "hull" of a the item, that is used as the walkaround ///> Returns a convex polygon "hull" of a the item, that is used as the walkaround
/// path. /// path.
/// aClearance defines how far from the body of the item the hull should be, /// aClearance defines how far from the body of the item the hull should be,
/// aWalkaroundThickness is the width of the line that walks around this hull. /// aWalkaroundThickness is the width of the line that walks around this hull.
virtual const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const
{ {
return SHAPE_LINE_CHAIN(); return SHAPE_LINE_CHAIN();
}; };
PnsKind GetKind() const { return m_kind; }
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; }
const std::string GetKindStr() const;
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; }
///> Net accessors ///> Gets/Sets the corresponding parent object in the host application's model (pcbnew)
int GetNet() const { return m_net; } void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; }
void SetNet(int aNet) { m_net = aNet; } BOARD_ITEM* GetParent() const { return m_parent; }
///> Layers accessors ///> Net accessors
const PNS_LAYERSET& GetLayers() const { return m_layers; } int GetNet() const { return m_net; }
void SetLayers ( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; } void SetNet( int aNet ) { m_net = aNet; }
void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); }
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned. ///> Layers accessors
void SetOwner (PNS_NODE *aOwner) { m_owner = aOwner; } const PNS_LAYERSET& GetLayers() const { return m_layers; }
bool BelongsTo (PNS_NODE *aNode) const { return m_owner == aNode; } void SetLayers( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; }
PNS_NODE *GetOwner() const { return m_owner; } void SetLayer( int aLayer )
{
m_layers = PNS_LAYERSET( aLayer, aLayer );
}
///> Sets the world that is used for collision resolution. ///> Ownership management. An item can belong to a single PNS_NODE or stay unowned.
void SetWorld (PNS_NODE *aWorld) { m_world = aWorld; } void SetOwner( PNS_NODE* aOwner ) { m_owner = aOwner; }
PNS_NODE *GetWorld() const { return m_world; } 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; }
///> Collision function. Checks if the item aOther is closer to us than ///> Collision function. Checks if the item aOther is closer to us than
/// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the /// aClearance and returns true if so. It can also calculate a minimum translation vector that
/// collision if needed. /// resolves the collision if needed.
virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
///> A shortcut without MTV calculation ///> A shortcut without MTV calculation
bool Collide( const PNS_ITEM *aOther, int aClearance ) const bool Collide( const PNS_ITEM* aOther, int aClearance ) const
{ {
VECTOR2I dummy; VECTOR2I dummy;
return Collide(aOther, aClearance, false, dummy);
} return Collide( aOther, aClearance, false, dummy );
}
///> Returns the geometric shape of the item
virtual const SHAPE* GetShape() const { ///> Returns the geometric shape of the item
return NULL; virtual const SHAPE* GetShape() const
} {
return NULL;
}
private: private:
bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const; bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV ) const;
protected: protected:
PnsKind m_kind;
PnsKind m_kind; BOARD_ITEM* m_parent;
PNS_NODE* m_world;
BOARD_ITEM *m_parent; PNS_NODE* m_owner;
PNS_NODE *m_world; PNS_LAYERSET m_layers;
PNS_NODE *m_owner;
PNS_LAYERSET m_layers;
bool m_movable; bool m_movable;
int m_net; int m_net;
}; };
#endif // __PNS_ITEM_H #endif // __PNS_ITEM_Ha

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -25,49 +25,58 @@
PNS_ITEMSET::PNS_ITEMSET() PNS_ITEMSET::PNS_ITEMSET()
{ {
} }
PNS_ITEMSET::~PNS_ITEMSET() PNS_ITEMSET::~PNS_ITEMSET()
{ {
} }
PNS_ITEMSET& PNS_ITEMSET::FilterLayers ( int aStart, int aEnd )
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
{ {
ItemVector newItems; ItemVector newItems;
PNS_LAYERSET l; PNS_LAYERSET l;
if(aEnd < 0)
l = PNS_LAYERSET(aStart);
else
l = PNS_LAYERSET(aStart, aEnd);
BOOST_FOREACH( PNS_ITEM *item, m_items ) if( aEnd < 0 )
if(item->GetLayers(). Overlaps ( l )) l = PNS_LAYERSET( aStart );
newItems.push_back(item); else
m_items = newItems; l = PNS_LAYERSET( aStart, aEnd );
return *this;
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; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if(item->GetKind() & aKindMask )
newItems.push_back(item); if( item->GetKind() & aKindMask )
m_items = newItems; newItems.push_back( item );
return *this;
m_items = newItems;
return *this;
} }
PNS_ITEMSET& PNS_ITEMSET::FilterNet ( int aNet )
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
{ {
ItemVector newItems; ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items ) BOOST_FOREACH( PNS_ITEM * item, m_items )
if(item->GetNet() == aNet)
newItems.push_back(item); if( item->GetNet() == aNet )
m_items = newItems; newItems.push_back( item );
return *this;
m_items = newItems;
return *this;
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -28,35 +28,36 @@
/** /**
* Class PNS_ITEMSET * Class PNS_ITEMSET
* *
* Holds a list of board items, that can be filtered against net, kinds, layers, etc. * Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/ **/
class PNS_ITEMSET class PNS_ITEMSET
{ {
public: public:
typedef std::vector<PNS_ITEM*> ItemVector;
typedef std::vector<PNS_ITEM *> ItemVector; PNS_ITEMSET();
~PNS_ITEMSET();
PNS_ITEMSET(); ItemVector& Items() { return m_items; }
~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 ); int Size() { return m_items.size(); }
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: private:
ItemVector m_items; ItemVector m_items;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -31,158 +31,177 @@
/** /**
* Class PNS_JOINT * Class PNS_JOINT
* *
* Represents a 2D point on a given set of layers and belonging to a certain net, * Represents a 2D point on a given set of layers and belonging to a certain
* that links together a number of board items. * net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items. * A hash table of joints is used by the router to follow connectivity between
* the items.
**/ **/
class PNS_JOINT : public PNS_ITEM class PNS_JOINT : public PNS_ITEM
{ {
public: public:
typedef std::vector<PNS_ITEM *> LinkedItems; typedef std::vector<PNS_ITEM*> LinkedItems;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed ///> Joints are hashed by their position, layers and net.
struct HashTag { /// Linked items are, obviously, not hashed
VECTOR2I pos; struct HashTag
int net; {
}; VECTOR2I pos;
int net;
PNS_JOINT(): };
PNS_ITEM(JOINT) {}
PNS_JOINT(const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1): PNS_JOINT() :
PNS_ITEM(JOINT) PNS_ITEM( JOINT ) {}
{
m_tag.pos = aPos;
m_tag.net = aNet;
m_layers = aLayers;
}
PNS_JOINT(const PNS_JOINT& b): PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
PNS_ITEM(JOINT) int aNet = -1 ) :
{ PNS_ITEM( JOINT )
m_layers = b.m_layers; {
m_tag.pos = b.m_tag.pos; m_tag.pos = aPos;
m_tag.net = b.m_tag.net; m_tag.net = aNet;
m_linkedItems = b.m_linkedItems; m_layers = aLayers;
m_layers = b.m_layers; }
}
PNS_ITEM *Clone() const PNS_JOINT( const PNS_JOINT& b ) :
{ PNS_ITEM( JOINT )
assert(false); {
return NULL; m_layers = b.m_layers;
} m_tag.pos = b.m_tag.pos;
m_tag.net = b.m_tag.net;
m_linkedItems = b.m_linkedItems;
m_layers = b.m_layers;
}
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer. PNS_ITEM* Clone() const
bool IsLineCorner() const {
{ assert( false );
if(m_linkedItems.size() != 2) return NULL;
return false; }
if( m_linkedItems[0]->GetKind() != SEGMENT || m_linkedItems[1]->GetKind() != SEGMENT ) ///> Returns true if the joint is a trivial line corner, connecting two
return false; /// segments of the same net, on the same layer.
bool IsLineCorner() const
{
if( m_linkedItems.size() != 2 )
return false;
PNS_SEGMENT *seg1 = static_cast<PNS_SEGMENT *> (m_linkedItems[0]); if( m_linkedItems[0]->GetKind() != SEGMENT ||
PNS_SEGMENT *seg2 = static_cast<PNS_SEGMENT *> (m_linkedItems[1]); m_linkedItems[1]->GetKind() != SEGMENT )
return false;
// joints between segments of different widths are not trivial. PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*> (m_linkedItems[0]);
return (seg1->GetWidth() == seg2->GetWidth()); PNS_SEGMENT* seg2 = static_cast<PNS_SEGMENT*> (m_linkedItems[1]);
}
///> Links the joint to a given board item (when it's added to the PNS_NODE) // joints between segments of different widths are not trivial.
void Link ( PNS_ITEM *aItem ) return seg1->GetWidth() == seg2->GetWidth();
{ }
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem);
if(f != m_linkedItems.end())
return;
m_linkedItems.push_back(aItem);
}
///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE) ///> Links the joint to a given board item (when it's added to the PNS_NODE)
///> Returns true if the joint became dangling after unlinking. void Link( PNS_ITEM* aItem )
bool Unlink ( PNS_ITEM *aItem ) {
{ LinkedItems::iterator f = std::find( m_linkedItems.begin(),
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem); 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 if( f != m_linkedItems.end() )
///> NULL, indicating the end of line. return;
PNS_SEGMENT* NextSegment( PNS_SEGMENT* aCurrent) const
{
if(!IsLineCorner())
return NULL;
return static_cast<PNS_SEGMENT *> (m_linkedItems [ m_linkedItems[0] == aCurrent ? 1 : 0 ] );
}
/// trivial accessors m_linkedItems.push_back( aItem );
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; };
///> Returns the number of linked items of types listed in aMask. ///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE)
int LinkCount( int aMask = -1 ) const ///> Returns true if the joint became dangling after unlinking.
{ bool Unlink( PNS_ITEM* aItem )
int n = 0; {
for(LinkedItems::const_iterator i = m_linkedItems.begin(); i!= m_linkedItems.end(); ++i) LinkedItems::iterator f = std::find( m_linkedItems.begin(),
if( (*i)->GetKind() & aMask ) m_linkedItems.end(), aItem );
n++;
return n;
}
void Dump() const; if( f != m_linkedItems.end() )
m_linkedItems.erase( f );
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 ) return m_linkedItems.size() == 0;
{ }
if(!Overlaps(aJoint))
return;
m_layers.Merge (aJoint.m_layers);
// fixme: duplicate links (?) ///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
for(LinkedItems::const_iterator i =aJoint.m_linkedItems.begin(); i!=aJoint.m_linkedItems.end();++i) ///> NULL, indicating the end of line.
m_linkedItems.push_back(*i); PNS_SEGMENT* NextSegment( PNS_SEGMENT* aCurrent ) const
} {
if( !IsLineCorner() )
return NULL;
bool Overlaps(const PNS_JOINT& rhs) const return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
{ }
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net && m_layers.Overlaps(rhs.m_layers);
} /// 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; };
///> 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 )
if( (*i)->GetKind() & aMask )
n++;
return n;
}
void Dump() 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 ) )
return;
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 );
}
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 );
}
private: private:
///> hash tag for unordered_multimap
HashTag m_tag;
///> hash tag for unordered_multimap ///> list of items linked to this joint
HashTag m_tag; LinkedItems m_linkedItems;
///> list of items linked to this joint
LinkedItems m_linkedItems;
}; };
// hash function & comparison operator for boost::unordered_map<> // hash function & comparison operator for boost::unordered_map<>
inline bool operator==(PNS_JOINT::HashTag const& p1, PNS_JOINT::HashTag const& p2) inline bool operator==( PNS_JOINT::HashTag const& p1,
PNS_JOINT::HashTag const& p2 )
{ {
return p1.pos == p2.pos && p1.net == p2.net; return p1.pos == p2.pos && p1.net == p2.net;
} }
inline std::size_t hash_value(PNS_JOINT::HashTag const& p)
inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
{ {
std::size_t seed = 0; std::size_t seed = 0;
boost::hash_combine(seed, p.pos.x); boost::hash_combine( seed, p.pos.x );
boost::hash_combine(seed, p.pos.y); boost::hash_combine( seed, p.pos.y );
boost::hash_combine(seed, p.net); boost::hash_combine( seed, p.net );
return seed; return seed;
} }
#endif // __PNS_JOINT_H #endif // __PNS_JOINT_H

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -26,93 +26,95 @@
/** /**
* Class PNS_LAYERSET * Class PNS_LAYERSET
* *
* Represents a contiguous set of PCB layers. * Represents a contiguous set of PCB layers.
*/ */
class PNS_LAYERSET class PNS_LAYERSET
{ {
public: public:
PNS_LAYERSET() :
m_start( -1 ),
m_end( -1 )
{};
PNS_LAYERSET(): PNS_LAYERSET( int aStart, int aEnd )
m_start(-1), {
m_end(-1) if( aStart > aEnd )
{}; std::swap( aStart, aEnd );
PNS_LAYERSET (int aStart, int aEnd) m_start = aStart;
{ m_end = 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; m_start = m_end = aLayer;
} }
PNS_LAYERSET(const PNS_LAYERSET &b) : PNS_LAYERSET( const PNS_LAYERSET& b ) :
m_start(b.m_start), m_start( b.m_start ),
m_end (b.m_end) m_end( b.m_end )
{} {}
~PNS_LAYERSET () {}; ~PNS_LAYERSET() {};
const PNS_LAYERSET& operator= ( const PNS_LAYERSET& b) const PNS_LAYERSET& operator=( const PNS_LAYERSET& b )
{ {
m_start = b.m_start; m_start = b.m_start;
m_end = b.m_end; m_end = b.m_end;
return *this; return *this;
} }
bool Overlaps ( const PNS_LAYERSET& aOther ) const bool Overlaps( const PNS_LAYERSET& aOther ) const
{ {
return m_end >= aOther.m_start && m_start <= aOther.m_end; return m_end >= aOther.m_start && m_start <= aOther.m_end;
} }
bool Overlaps ( const int aLayer ) const bool Overlaps( const int aLayer ) const
{ {
return aLayer >= m_start && aLayer <= m_end; return aLayer >= m_start && aLayer <= m_end;
} }
bool IsMultilayer ( ) const bool IsMultilayer() const
{ {
return m_start != m_end; return m_start != m_end;
} }
int Start() const { int Start() const
return m_start; {
} return m_start;
}
int End() const { int End() const
return m_end; {
} return m_end;
}
void Merge ( const PNS_LAYERSET& aOther ) void Merge( const PNS_LAYERSET& aOther )
{ {
if(m_start < 0 || m_end < 0) if( m_start < 0 || m_end < 0 )
{ {
m_start = aOther.m_start; m_start = aOther.m_start;
m_end = aOther.m_end; m_end = aOther.m_end;
return; return;
} }
if(aOther.m_start < m_start) if( aOther.m_start < m_start )
m_start = aOther.m_start; m_start = aOther.m_start;
if(aOther.m_end > m_end)
m_end = aOther.m_end;
}
///> Shortcut for comparisons/overlap tests if( aOther.m_end > m_end )
static PNS_LAYERSET All() m_end = aOther.m_end;
{ }
return PNS_LAYERSET(0, 256);
}
private: ///> Shortcut for comparisons/overlap tests
static PNS_LAYERSET All()
{
return PNS_LAYERSET( 0, 256 );
}
int m_start; private:
int m_end; int m_start;
int m_end;
}; };
#endif // __PNS_LAYERSET_H #endif // __PNS_LAYERSET_H

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -38,214 +38,227 @@ class PNS_VIA;
/** /**
* Class PNS_LINE * Class PNS_LINE
* *
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads, * Represents a track on a PCB, connecting two non-trivial joints (that is,
* junctions between multiple traces or two traces different widths and combinations of these). * vias, pads, junctions between multiple traces or two traces different widths
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on * and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* a via/pad/segment that belongs/begins them. * Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
* *
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments * PNS_LINEs can be either loose (consisting of segments that do not belong to
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends. * any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* * returned by PNS_NODE::AssembleLine and friends.
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff. *
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/ */
class PNS_LINE : public PNS_ITEM class PNS_LINE : public PNS_ITEM
{ {
public: public:
typedef std::vector<PNS_SEGMENT *> LinkedSegments; typedef std::vector<PNS_SEGMENT*> LinkedSegments;
PNS_LINE (): PNS_LINE() :
PNS_ITEM(LINE) PNS_ITEM( LINE )
{ {
m_segmentRefs = NULL; m_segmentRefs = NULL;
m_hasVia = false; m_hasVia = false;
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
}; };
PNS_LINE (int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine) : PNS_LINE( int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine ) :
PNS_ITEM(LINE) PNS_ITEM( LINE )
{ {
m_line = aLine; m_line = aLine;
m_width = aWidth; m_width = aWidth;
m_segmentRefs = NULL; m_segmentRefs = NULL;
m_hasVia = false; m_hasVia = false;
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
SetLayer(aLayer); SetLayer( aLayer );
}
} PNS_LINE( const PNS_LINE& aOther ) :
PNS_ITEM( aOther ),
m_line( aOther.m_line ),
m_width( aOther.m_width )
{
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_world = aOther.m_world;
m_layers = aOther.m_layers;
m_segmentRefs = NULL;
m_via = aOther.m_via;
m_hasVia = aOther.m_hasVia;
m_affectedRangeStart = -1;
}
PNS_LINE(const PNS_LINE& aOther) : /**
PNS_ITEM(aOther), * Constructor
m_line(aOther.m_line), * copies properties (net, layers from a base line), and replaces the shape
m_width(aOther.m_width) * by aLine
{ **/
m_net = aOther.m_net; PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) :
m_movable = aOther.m_movable; PNS_ITEM( aBase ),
m_world = aOther.m_world; m_line( aLine ),
m_layers = aOther.m_layers; m_width( aBase.m_width )
m_segmentRefs = NULL; {
m_via = aOther.m_via; m_net = aBase.m_net;
m_hasVia = aOther.m_hasVia; m_layers = aBase.m_layers;
m_affectedRangeStart = -1; m_segmentRefs = NULL;
} m_hasVia = false;
m_affectedRangeStart = -1;
}
/** ~PNS_LINE()
* Constructor {
* copies properties (net, layers from a base line), and replaces the shape if( m_segmentRefs )
* by aLine delete m_segmentRefs;
**/ };
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;
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
}
~PNS_LINE () virtual PNS_LINE* Clone() const;
{
if(m_segmentRefs)
delete m_segmentRefs;
};
virtual PNS_LINE *Clone() 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 ///> clones the line without cloning the shape
void SetShape(const SHAPE_LINE_CHAIN& aLine) { m_line = aLine; } ///> (just the properties - net, width, layers, etc.)
const SHAPE* GetShape() const { return &m_line; } PNS_LINE* CloneProperties() const;
SHAPE_LINE_CHAIN& GetLine() { return m_line; }
const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
///> Width accessors int GetLayer() const { return GetLayers().Start(); }
void SetWidth( int aWidth ) { m_width = aWidth; }
int GetWidth () const { return m_width; }
///> Links a segment from a PNS_NODE to this line, making it owned by the node ///> Geometry accessors
void LinkSegment(PNS_SEGMENT *aSeg) void SetShape( const SHAPE_LINE_CHAIN& aLine ) { m_line = aLine; }
{ const SHAPE* GetShape() const { return &m_line; }
if(!m_segmentRefs) SHAPE_LINE_CHAIN& GetLine() { return m_line; }
m_segmentRefs = new std::vector<PNS_SEGMENT *> (); const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
m_segmentRefs->push_back(aSeg);
}
///> Returns a list of segments from the owning node that constitute this line (or NULL if ///> Width accessors
///> the line is loose) void SetWidth( int aWidth ) { m_width = aWidth; }
LinkedSegments* GetLinkedSegments() int GetWidth() const { return m_width; }
{
return m_segmentRefs;
}
bool ContainsSegment (PNS_SEGMENT *aSeg) const ///> Links a segment from a PNS_NODE to this line, making it owned by the node
{ void LinkSegment( PNS_SEGMENT* aSeg )
if (!m_segmentRefs) {
return false; if( !m_segmentRefs )
m_segmentRefs = new std::vector<PNS_SEGMENT*> ();
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end(); m_segmentRefs->push_back( aSeg );
} }
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision. ///> Returns a list of segments from the owning node that constitute this
const PNS_LINE ClipToNearestObstacle( PNS_NODE *aNode ) const; ///> line (or NULL if the line is loose)
LinkedSegments* GetLinkedSegments()
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER) {
bool MergeObtuseSegments(); return m_segmentRefs;
bool MergeSegments(); }
///> Returns the number of corners of angles specified by mask aAngles. bool ContainsSegment( PNS_SEGMENT* aSeg ) const
int CountCorners(int aAngles); {
if( !m_segmentRefs )
return false;
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;
///> 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 );
///> 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
///> aCW = whether to walkaround in clockwise or counter-clockwise direction.
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPrePath,
SHAPE_LINE_CHAIN& aWalkaroundPath,
SHAPE_LINE_CHAIN& aPostPath,
bool aCw ) const;
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath,
bool aCw ) const;
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle). bool Walkaround( SHAPE_LINE_CHAIN obstacle,
///> aPrePath = path from origin to the obstacle SHAPE_LINE_CHAIN& pre,
///> aWalkaroundPath = path around the obstacle SHAPE_LINE_CHAIN& walk,
///> aPostPath = past from obstacle till the end SHAPE_LINE_CHAIN& post,
///> aCW = whether to walkaround in clockwise or counter-clockwise direction. bool cw ) const;
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPrePath,
SHAPE_LINE_CHAIN& aWalkaroundPath,
SHAPE_LINE_CHAIN& aPostPath,
bool aCw ) const;
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath, SHAPE_LINE_CHAIN& aPath,
bool aCw ) const; bool aCw ) const;
bool 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, bool Is45Degree();
SHAPE_LINE_CHAIN& aPath,
bool aCw ) const;
bool Is45Degree(); ///> Prints out all linked segments
void ShowLinks();
///> Prints out all linked segments bool EndsWithVia() const { return m_hasVia; }
void ShowLinks();
bool EndsWithVia() const { return m_hasVia; } void AppendVia( const PNS_VIA& aVia )
{
void AppendVia ( const PNS_VIA &aVia ) { m_hasVia = true;
m_hasVia = true; m_via = aVia;
m_via = aVia; m_via.SetNet( m_net );
m_via.SetNet ( m_net ) ; }
}
void RemoveVia() { m_hasVia = false; } void RemoveVia() { m_hasVia = false; }
const PNS_VIA& GetVia() const { return m_via; } const PNS_VIA& GetVia() const { return m_via; }
void SetAffectedRange ( int aStart, int aEnd ) void SetAffectedRange( int aStart, int aEnd )
{ {
m_affectedRangeStart = aStart; m_affectedRangeStart = aStart;
m_affectedRangeEnd = aEnd; m_affectedRangeEnd = aEnd;
} }
void ClearAffectedRange ( ) void ClearAffectedRange()
{ {
m_affectedRangeStart = -1; m_affectedRangeStart = -1;
} }
bool GetAffectedRange ( int& aStart, int& aEnd ) bool GetAffectedRange( int& aStart, int& aEnd )
{ {
if(m_affectedRangeStart >= 0) if( m_affectedRangeStart >= 0 )
{ {
aStart = m_affectedRangeStart; aStart = m_affectedRangeStart;
aEnd = m_affectedRangeEnd; aEnd = m_affectedRangeEnd;
return true; return true;
} else { }
aStart = 0; else
aEnd = m_line.PointCount(); {
return false; aStart = 0;
} aEnd = m_line.PointCount();
} return false;
}
}
private: private:
bool onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const; bool onEdge( const SHAPE_LINE_CHAIN& obstacle, VECTOR2I p, int& ei, bool& is_vertex ) const;
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const; bool walkScan( const SHAPE_LINE_CHAIN& line, const SHAPE_LINE_CHAIN& obstacle,
bool reverse, VECTOR2I& ip, int& index_o, int& index_l, bool& is_vertex ) const;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments* m_segmentRefs;
///> Shape of the line
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;
int m_affectedRangeStart; ///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
int m_affectedRangeEnd; LinkedSegments* m_segmentRefs;
///> Shape of the line
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;
int m_affectedRangeStart;
int m_affectedRangeEnd;
}; };
#endif // __PNS_LINE_H
#endif // __PNS_LINE_H

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -30,7 +30,7 @@
#include "pns_via.h" #include "pns_via.h"
#include "pns_line.h" #include "pns_line.h"
#include "pns_routing_settings.h" #include "pns_routing_settings.h"
class PNS_ROUTER; class PNS_ROUTER;
class PNS_SHOVE; class PNS_SHOVE;
class PNS_OPTIMIZER; class PNS_OPTIMIZER;
@ -39,118 +39,217 @@ class PNS_ROUTER_BASE;
/** /**
* Class PNS_LINE_PLACER * Class PNS_LINE_PLACER
* *
* Interactively routes a single track. Runs shove and walkaround algorithms when needed. * Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/ */
class PNS_LINE_PLACER class PNS_LINE_PLACER
{ {
public: public:
PNS_LINE_PLACER( PNS_NODE *aWorld ); PNS_LINE_PLACER( PNS_NODE* aWorld );
~PNS_LINE_PLACER(); ~PNS_LINE_PLACER();
///> Appends a via at the end of currently placed line. ///> Appends a via at the end of currently placed line.
void AddVia ( bool aEnabled, int aDiameter, int aDrill ) void AddVia( bool aEnabled, int aDiameter, int aDrill )
{ {
m_viaDiameter = aDiameter; m_viaDiameter = aDiameter;
m_viaDrill = aDrill; m_viaDrill = aDrill;
m_placingVia = aEnabled; m_placingVia = aEnabled;
} }
///> Starts placement of a line at point aStart. ///> Starts placement of a line at point aStart.
void StartPlacement(const VECTOR2I& aStart, int aNet, int aWidth, int aLayer); void StartPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer );
///> Updates the routed line with a new ending point.
bool Route(const VECTOR2I& aP);
///> Sets initial routing direction/posture
void SetInitialDirection(const DIRECTION_45& aDirection);
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 /**
const PNS_LINE& GetHead() const { return m_head; } * Function Route()
///> 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; } * 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 );
///> Returns the whole routed line ///> Sets initial routing direction/posture
const PNS_LINE GetTrace() const; void SetInitialDirection( const DIRECTION_45& aDirection );
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions. void ApplySettings( const PNS_ROUTING_SETTINGS& aSettings );
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);
else
return m_p_start;
}
///> 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)
const PNS_LINE& GetTail() const { return m_tail; }
///> Returns all items in the world that have been affected by the routing operation. Used ///> Returns the whole routed line
/// to update data structures of the host application const PNS_LINE GetTrace() const;
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 ///> Returns the current end of the line being placed. It may not be equal
PNS_NODE *GetCurrentNode() const; ///> 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 );
else
return m_p_start;
}
private: ///> Returns all items in the world that have been affected by the routing
///> operation. Used to update data structures of the host application
static const double m_shoveLengthThreshold = 1.7; void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved,
PNS_NODE::ItemVector& aAdded );
bool handleViaPlacement ( PNS_LINE& aHead ); ///> Toggles the current posture (straight/diagonal) of the trace head.
void FlipPosture();
bool checkObtusity(const SEG& a, const SEG& b) const; ///> Returns the most recent world state
bool handleSelfIntersections(); PNS_NODE* GetCurrentNode() const;
bool handlePullback();
bool mergeHead();
bool reduceTail(const VECTOR2I& aEnd);
void fixHeadPosture();
bool optimizeTailHeadTransition();
bool routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround = true);
void routeStep(const VECTOR2I& aP);
///> routing mode (walkaround, shove, etc.) private:
PNS_MODE m_mode; static const double m_shoveLengthThreshold = 1.7;
///> follow mouse trail by attaching new segments to the head as the cursor moves
bool m_follow_mouse; bool handleViaPlacement( PNS_LINE& aHead );
///> mouse smoothing active
bool m_smooth_mouse; /**
///> mouse smoothing step (in world units) * Function checkObtusity()
int m_smoothing_step; *
///> current routing direction * Helper that checks if segments a and b form an obtuse angle
DIRECTION_45 m_direction; * (in 45-degree regime).
///> routing direction for new traces * @return true, if angle (a, b) is obtuse
DIRECTION_45 m_initial_direction; */
///> routing "head": volatile part of the track from the previously bool checkObtusity( const SEG& a, const SEG& b ) const;
/// 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 * Function handleSelfIntersections()
PNS_LINE m_tail; *
///> current algorithm iteration * Checks if the head of the track intersects its tail. If so, cuts the
int m_iteration; * tail up to the intersecting segment and fixes the head direction to match
///> pointer to world to search colliding items * the last segment before the cut.
PNS_NODE *m_world; * @return true if the line has been changed.
///> current routing start point (end of tail, beginning of head) */
VECTOR2I m_p_start; bool handleSelfIntersections();
///> The shove engine
PNS_SHOVE *m_shove; /**
///> Current world state * Function handlePullback()
PNS_NODE *m_currentNode; *
///> Are we placing a via? * Deals with pull-back: reduces the tail if head trace is moved backwards
bool m_placingVia; * wrs to the current tail direction.
///> current via diameter * @return true if the line has been changed.
int m_viaDiameter; */
///> current via drill bool handlePullback();
int m_viaDrill;
///> walkaround algorithm iteration limit /**
int m_walkaroundIterationLimit; * Function mergeHead()
///> smart pads optimizer enabled. *
bool m_smartPads; * Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
bool mergeHead();
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a
* certain number of latest tail segments with a direct trace leading to aEnd
* that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool reduceTail( const VECTOR2I& aEnd );
void fixHeadPosture();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
bool optimizeTailHeadTransition();
/**
* 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
bool m_follow_mouse;
///> mouse smoothing active
bool m_smooth_mouse;
///> mouse smoothing step (in world units)
int m_smoothing_step;
///> current routing direction
DIRECTION_45 m_direction;
///> routing direction for new traces
DIRECTION_45 m_initial_direction;
///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination
PNS_LINE m_head;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE m_tail;
///> current algorithm iteration
int m_iteration;
///> pointer to world to search colliding items
PNS_NODE* m_world;
///> current routing start point (end of tail, beginning of head)
VECTOR2I m_p_start;
///> The shove engine
PNS_SHOVE* m_shove;
///> Current world state
PNS_NODE* m_currentNode;
///> Are we placing a via?
bool m_placingVia;
///> current via diameter
int m_viaDiameter;
///> current via drill
int m_viaDrill;
///> walkaround algorithm iteration limit
int m_walkaroundIterationLimit;
///> smart pads optimizer enabled.
bool m_smartPads;
}; };
#endif // __PNS_LINE_PLACER_H #endif // __PNS_LINE_PLACER_H

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -45,9 +45,10 @@ class PNS_INDEX;
using boost::shared_ptr; using boost::shared_ptr;
class PNS_CLEARANCE_FUNC { class PNS_CLEARANCE_FUNC
public: {
virtual int operator() ( const PNS_ITEM *a , const PNS_ITEM *b) = 0; public:
virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0;
}; };
/** /**
@ -56,205 +57,225 @@ class PNS_CLEARANCE_FUNC {
* Holds an object colliding with another object, along with * Holds an object colliding with another object, along with
* some useful data about the collision. * some useful data about the collision.
**/ **/
struct PNS_OBSTACLE struct PNS_OBSTACLE
{ {
///> Item we search collisions with ///> Item we search collisions with
PNS_ITEM *head; PNS_ITEM* head;
///> Item found to be colliding with head
PNS_ITEM *item;
///> Hull of the colliding item ///> Item found to be colliding with head
SHAPE_LINE_CHAIN hull; PNS_ITEM* item;
///> First and last intersection point between the head item and the hull of the ///> Hull of the colliding item
//// colliding item SHAPE_LINE_CHAIN hull;
VECTOR2I ip_first, ip_last;
///> First and last intersection point between the head item and the hull
///> ... and the distance thereof ///> of the colliding item
int dist_first, dist_last; VECTOR2I ip_first, ip_last;
///> ... and the distance thereof
int dist_first, dist_last;
}; };
/** /**
* Class PNS_NODE * Class PNS_NODE
* *
* Keeps the router "world" - i.e. all the tracks, vias, solids in a hierarchical and indexed way. * Keeps the router "world" - i.e. all the tracks, vias, solids in a
* hierarchical and indexed way.
* Features: * Features:
* - spatial-indexed container for PCB item shapes * - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking) * - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths * - assembly of lines connecting joints, finding loops and unique paths
* - lightweight cloning/branching (for recursive optimization and shove springback) * - lightweight cloning/branching (for recursive optimization and shove
* springback)
**/ **/
class PNS_NODE { class PNS_NODE
{
public: public:
typedef boost::optional<PNS_OBSTACLE> OptObstacle;
typedef boost::optional<PNS_OBSTACLE> OptObstacle; typedef std::vector<PNS_ITEM*> ItemVector;
typedef std::vector<PNS_ITEM *> ItemVector; typedef std::vector<PNS_OBSTACLE> Obstacles;
typedef std::vector<PNS_OBSTACLE> Obstacles; typedef boost::optional<PNS_JOINT> OptJoint;
typedef boost::optional<PNS_JOINT> OptJoint;
PNS_NODE (); PNS_NODE();
~PNS_NODE (); ~PNS_NODE();
///> Returns the expected clearance between items a and b. ///> Returns the expected clearance between items a and b.
int GetClearance(const PNS_ITEM *a, const PNS_ITEM *b) const; int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const;
///> Returns the pre-set worst case clearance between any pair of items
int GetMaxClearance() const
{
return m_maxClearance;
}
void SetMaxClearance( int aClearance ) ///> Returns the pre-set worst case clearance between any pair of items
{ int GetMaxClearance() const
m_maxClearance = aClearance; {
} return m_maxClearance;
}
void SetClearanceFunctor (PNS_CLEARANCE_FUNC *aFunc) void SetMaxClearance( int aClearance )
{ {
m_clearanceFunctor = aFunc; m_maxClearance = aClearance;
} }
///> Finds items that collide with aItem and stores collision information in aObstacles. void SetClearanceFunctor( PNS_CLEARANCE_FUNC* aFunc )
int QueryColliding( const PNS_ITEM* aItem, Obstacles& aObstacles, int aKindMask = PNS_ITEM::ANY, int aLimitCount = -1); {
m_clearanceFunctor = aFunc;
}
///> Finds the nearest item that collides with aItem. ///> Finds items that collide with aItem and stores collision information
OptObstacle NearestObstacle( const PNS_LINE *aItem, int aKindMask = PNS_ITEM::ANY); ///> in aObstacles.
int QueryColliding( const PNS_ITEM* aItem,
Obstacles& aObstacles,
int aKindMask = PNS_ITEM::ANY,
int aLimitCount = -1 );
///> Checks if the item collides with anything else in the world, and returns it if so. ///> Finds the nearest item that collides with aItem.
OptObstacle CheckColliding ( const PNS_ITEM *aItem, int aKindMask = PNS_ITEM::ANY); OptObstacle NearestObstacle( const PNS_LINE* aItem, int aKindMask = PNS_ITEM::ANY );
///> Checks if two items collide [deprecated]. ///> Checks if the item collides with anything else in the world,
bool CheckColliding( const PNS_ITEM *aItemA, const PNS_ITEM *aItemB, int aKindMask = PNS_ITEM::ANY); ///> and returns it if so.
OptObstacle CheckColliding( const PNS_ITEM* aItem, int aKindMask = PNS_ITEM::ANY );
///> Hit detection ///> Checks if two items collide [deprecated].
const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ); bool CheckColliding( const PNS_ITEM* aItemA,
const PNS_ITEM* aItemB,
int aKindMask = PNS_ITEM::ANY );
void Add(PNS_ITEM *aItem); ///> Hit detection
void Remove(PNS_ITEM *aItem); const PNS_ITEMSET HitTest( const VECTOR2I& aPoint );
void Replace(PNS_ITEM *aOldItem, PNS_ITEM *aNewItem);
///> Creates a lightweight copy ("branch") of self. Note that if there are any branches void Add( PNS_ITEM* aItem );
/// in use, their parents must NOT be deleted. void Remove( PNS_ITEM* aItem );
PNS_NODE *Branch(); void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
///> Assembles a line connecting two non-trivial joints the segment aSeg belongs to. ///> Creates a lightweight copy ("branch") of self. Note that if there are
PNS_LINE *AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint()); ///> any branches in use, their parents must NOT be deleted.
PNS_NODE* Branch();
///> Dumps the contents and joints structure
void Dump(bool aLong = false);
///> Returns the number of joints ///> Assembles a line connecting two non-trivial joints the
int JointCount() const ///> segment aSeg belongs to.
{ PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg,
return m_joints.size(); const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() );
}
///> Returns the lists of items removed and added in this branch, with respect ///> Dumps the contents and joints structure
///> to the root. void Dump( bool aLong = false );
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded);
///> Copies the changes from a given branch (aNode) to the root. Called on ///> Returns the number of joints
///> a non-root branch will fail. int JointCount() const
void Commit (PNS_NODE *aNode); {
return m_joints.size();
}
///> finds a joint at a given position, layer and nets ///> Returns the lists of items removed and added in this branch, with
const OptJoint FindJoint(const VECTOR2I &aPos, int aLayer, int aNet); ///> respect to the root.
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded );
///> finds all linest between a pair of joints. Used by the loop removal engine. ///> Copies the changes from a given branch (aNode) to the root. Called on
int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector<PNS_LINE *> &aLines ); ///> a non-root branch will fail.
void Commit( PNS_NODE* aNode );
///> finds the joints corresponding to the ends of line aLine ///> finds a joint at a given position, layer and nets
void FindLineEnds (PNS_LINE *aLine, PNS_JOINT& a, PNS_JOINT& b ); const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
///> finds all joints that have an (in)direct connection(s) (i.e. segments/vias) with the joint aJoint. ///> finds all linest between a pair of joints. Used by the loop removal engine.
void FindConnectedJoints( const PNS_JOINT& aJoint, std::vector<PNS_JOINT *> &aConnectedJoints ); int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b,
std::vector<PNS_LINE*>& aLines );
///> Destroys all child nodes. Applicable only to the root node. ///> finds the joints corresponding to the ends of line aLine
void KillChildren(); void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b );
void AllItemsInNet ( int aNet, std::list<PNS_ITEM *>& aItems); ///> finds all joints that have an (in)direct connection(s)
///> (i.e. segments/vias) with the joint aJoint.
void FindConnectedJoints( const PNS_JOINT& aJoint,
std::vector<PNS_JOINT*>& aConnectedJoints );
///> Destroys all child nodes. Applicable only to the root node.
void KillChildren();
void AllItemsInNet( int aNet, std::list<PNS_ITEM*>& aItems );
private: private:
struct obstacleVisitor;
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap;
typedef JointMap::value_type TagJointPair;
struct obstacleVisitor; /// nodes are not copyable
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap; PNS_NODE( const PNS_NODE& b );
typedef JointMap::value_type TagJointPair; PNS_NODE& operator=( const PNS_NODE& b );
/// nodes are not copyable ///> tries to find matching joint and creates a new one if not found
PNS_NODE( const PNS_NODE& b); PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
PNS_NODE &operator=(const PNS_NODE& b); int aNet );
///> tries to find matching joint and creates a new one if not found
PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet );
///> touches a joint and links it to an item
void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere );
///> unlinks an item from a joint ///> touches a joint and links it to an item
void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere ); void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet, PNS_ITEM* aWhere );
///> helpers for adding/removing items
void addSolid( PNS_SOLID *aSeg ); ///> unlinks an item from a joint
void addSegment( PNS_SEGMENT *aSeg ); void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
void addLine( PNS_LINE *aLine ); int aNet, PNS_ITEM* aWhere );
void addVia( PNS_VIA *aVia );
void removeSolid( PNS_SOLID *aSeg );
void removeLine( PNS_LINE *aLine );
void removeSegment (PNS_SEGMENT *aSeg );
void removeVia (PNS_VIA *aVia );
void doRemove( PNS_ITEM *aItem ); ///> helpers for adding/removing items
void unlinkParent ( ); void addSolid( PNS_SOLID* aSeg );
void releaseChildren (); void addSegment( PNS_SEGMENT* aSeg );
void addLine( PNS_LINE* aLine );
bool isRoot() const void addVia( PNS_VIA* aVia );
{ void removeSolid( PNS_SOLID* aSeg );
return m_parent == NULL; void removeLine( PNS_LINE* aLine );
} void removeSegment( PNS_SEGMENT* aSeg );
void removeVia( PNS_VIA* aVia );
///> checks if this branch contains an updated version of the item from the root branch. void doRemove( PNS_ITEM* aItem );
bool overrides ( PNS_ITEM * aItem ) const void unlinkParent();
{ void releaseChildren();
return m_override.find(aItem) != m_override.end();
}
///> scans the joint map, forming a line starting from segment (current). bool isRoot() const
void followLine(PNS_SEGMENT *current, bool scanDirection, int& pos, int limit, VECTOR2I *corners, PNS_SEGMENT **segments); {
return m_parent == NULL;
}
///> spatial index of all items ///> checks if this branch contains an updated version of the item
//SHAPE_INDEX_LIST<PNS_ITEM *> m_items; ///> from the root branch.
bool overrides( PNS_ITEM* aItem ) const
///> hash table with the joints, linking the items. Joints are hashed by their {
///> position, layer set and net. return m_override.find( aItem ) != m_override.end();
JointMap m_joints; }
///> node this node was branched from ///> scans the joint map, forming a line starting from segment (current).
PNS_NODE *m_parent; void followLine( PNS_SEGMENT* current,
bool scanDirection,
int& pos,
int limit,
VECTOR2I* corners,
PNS_SEGMENT** segments );
///> root node of the whole hierarchy ///> spatial index of all items
PNS_NODE *m_root; // SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
///> list of nodes branched from this one
std::vector<PNS_NODE *> m_children;
///> hash of root's items that are more recent in this node ///> hash table with the joints, linking the items. Joints are hashed by
boost::unordered_set<PNS_ITEM *> m_override; ///> their position, layer set and net.
JointMap m_joints;
///> worst case item-item clearance ///> node this node was branched from
int m_maxClearance; PNS_NODE* m_parent;
///> Clearance resolution functor
PNS_CLEARANCE_FUNC *m_clearanceFunctor;
///> Geometric/Net index of the items ///> root node of the whole hierarchy
PNS_INDEX *m_index; PNS_NODE* m_root;
///> list of currently processed obstacles. ///> list of nodes branched from this one
Obstacles m_obstacleList; std::vector<PNS_NODE*> m_children;
///> hash of root's items that are more recent in this node
boost::unordered_set<PNS_ITEM*> m_override;
///> worst case item-item clearance
int m_maxClearance;
///> Clearance resolution functor
PNS_CLEARANCE_FUNC* m_clearanceFunctor;
///> Geometric/Net index of the items
PNS_INDEX* m_index;
///> list of currently processed obstacles.
Obstacles m_obstacleList;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -3,20 +3,21 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_OPTIMIZER_H #ifndef __PNS_OPTIMIZER_H
#define __PNS_OPTIMIZER_H #define __PNS_OPTIMIZER_H
@ -30,135 +31,137 @@ class PNS_NODE;
class PNS_LINE; class PNS_LINE;
class PNS_ROUTER; class PNS_ROUTER;
/** /**
* Class PNS_COST_ESTIMATOR * Class PNS_COST_ESTIMATOR
* *
* Calculates the cost of a given line, taking corner angles and total length into account. * Calculates the cost of a given line, taking corner angles and total length into account.
**/ **/
class PNS_COST_ESTIMATOR class PNS_COST_ESTIMATOR
{ {
public: public:
PNS_COST_ESTIMATOR(): PNS_COST_ESTIMATOR() :
m_lengthCost (0), m_lengthCost( 0 ),
m_cornerCost (0) m_cornerCost( 0 )
{}; {};
PNS_COST_ESTIMATOR(const PNS_COST_ESTIMATOR &b): PNS_COST_ESTIMATOR( const PNS_COST_ESTIMATOR& b ) :
m_lengthCost (b.m_lengthCost), m_lengthCost( b.m_lengthCost ),
m_cornerCost (b.m_cornerCost) m_cornerCost( b.m_cornerCost )
{}; {};
~PNS_COST_ESTIMATOR() {}; ~PNS_COST_ESTIMATOR() {};
static int CornerCost ( const SEG& a, const SEG& b);
static int CornerCost ( const SHAPE_LINE_CHAIN& aLine );
static int CornerCost ( const PNS_LINE& aLine);
void Add(PNS_LINE &aLine); static int CornerCost( const SEG& a, const SEG& b );
void Remove (PNS_LINE &aLine); static int CornerCost( const SHAPE_LINE_CHAIN& aLine );
void Replace(PNS_LINE &aOldLine, PNS_LINE& aNewLine); static int CornerCost( const PNS_LINE& aLine );
bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance, double aCornerTollerace ) const;
double GetLengthCost() const { return m_lengthCost; } void Add( PNS_LINE& aLine );
double GetCornerCost() const { return m_cornerCost; } void Remove( PNS_LINE& aLine );
void Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine );
private: bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance,
double m_lengthCost; double aCornerTollerace ) const;
int m_cornerCost;
double GetLengthCost() const { return m_lengthCost; }
double GetCornerCost() const { return m_cornerCost; }
private:
double m_lengthCost;
int m_cornerCost;
}; };
/** /**
* Class PNS_OPTIMIZER * Class PNS_OPTIMIZER
* *
* Performs various optimizations of the lines being routed, attempting to make the lines shorter * Performs various optimizations of the lines being routed, attempting to make the lines shorter
* and less cornery. There are 3 kinds of optimizations so far: * and less cornery. There are 3 kinds of optimizations so far:
* - Merging obtuse segments (MERGE_OBTUSE): tries to join together as many * - Merging obtuse segments (MERGE_OBTUSE): tries to join together as many
* obtuse segments as possible without causing collisions * obtuse segments as possible without causing collisions
* - Rerouting path between pair of line corners with a 2-segment "\__" line and iteratively repeating * - Rerouting path between pair of line corners with a 2-segment "\__" line and iteratively repeating
* the procedure as long as the total cost of the line keeps decreasing * the procedure as long as the total cost of the line keeps decreasing
* - "Smart Pads" - that is, rerouting pad/via exits to make them look nice (SMART_PADS). * - "Smart Pads" - that is, rerouting pad/via exits to make them look nice (SMART_PADS).
**/ **/
class PNS_OPTIMIZER class PNS_OPTIMIZER
{ {
public: public:
enum OptimizationEffort
{
MERGE_SEGMENTS = 0x01,
SMART_PADS = 0x02,
MERGE_OBTUSE = 0x04
};
enum OptimizationEffort { PNS_OPTIMIZER( PNS_NODE* aWorld );
MERGE_SEGMENTS = 0x1, ~PNS_OPTIMIZER();
SMART_PADS = 0x2,
MERGE_OBTUSE = 0x4
};
PNS_OPTIMIZER( PNS_NODE *aWorld ); ///> a quick shortcut to optmize a line without creating and setting up an optimizer
~PNS_OPTIMIZER(); static bool Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorld = NULL );
///> a quick shortcut to optmize a line without creating and setting up an optimizer bool Optimize( PNS_LINE* aLine, PNS_LINE* aResult = NULL,
static bool Optimize ( PNS_LINE *aLine, int aEffortLevel, PNS_NODE *aWorld = NULL ); int aStartVertex = 0, int aEndVertex = -1 );
bool Optimize ( PNS_LINE *aLine, PNS_LINE *aResult = NULL, int aStartVertex = 0, int aEndVertex = -1); void SetWorld( PNS_NODE* aNode ) { m_world = aNode; }
void CacheStaticItem( PNS_ITEM* aItem );
void CacheRemove( PNS_ITEM* aItem );
void ClearCache( bool aStaticOnly = false );
void SetWorld(PNS_NODE *aNode) { m_world = aNode; } void SetCollisionMask( int aMask )
void CacheStaticItem (PNS_ITEM *aItem); {
void CacheRemove( PNS_ITEM *aItem ); m_collisionKindMask = aMask;
void ClearCache( bool aStaticOnly = false ); }
void SetCollisionMask ( int aMask ) void SetEffortLevel( int aEffort )
{ {
m_collisionKindMask = aMask; m_effortLevel = aEffort;
} }
void SetEffortLevel ( int aEffort ) private:
{ static const int MaxCachedItems = 256;
m_effortLevel = aEffort;
}
private:
static const int MaxCachedItems = 256; typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList;
typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList; struct CacheVisitor;
struct CacheVisitor; struct CachedItem
{
struct CachedItem int hits;
{ bool isStatic;
int hits; };
bool isStatic;
};
bool mergeObtuse (PNS_LINE *aLine); bool mergeObtuse( PNS_LINE* aLine );
bool mergeFull (PNS_LINE *aLine); bool mergeFull( PNS_LINE* aLine );
bool removeUglyCorners (PNS_LINE *aLine); bool removeUglyCorners( PNS_LINE* aLine );
bool runSmartPads(PNS_LINE *aLine); bool runSmartPads( PNS_LINE* aLine );
bool mergeStep ( PNS_LINE *aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step ); bool mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step );
bool checkColliding( PNS_ITEM *aItem, bool aUpdateCache = true ); bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true );
bool checkColliding( PNS_LINE *aLine, const SHAPE_LINE_CHAIN& aOptPath ); bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath );
void cacheAdd( PNS_ITEM *aItem, bool aIsStatic ); void cacheAdd( PNS_ITEM* aItem, bool aIsStatic );
void removeCachedSegments (PNS_LINE *aLine, int aStartVertex = 0, int aEndVertex = -1); void removeCachedSegments( PNS_LINE* aLine, int aStartVertex = 0, int aEndVertex = -1 );
BreakoutList circleBreakouts( int aWidth, const SHAPE *aShape, bool aPermitDiagonal ) const; BreakoutList circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList rectBreakouts( int aWidth, const SHAPE *aShape, bool aPermitDiagonal ) const; BreakoutList rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList ovalBreakouts( int aWidth, const SHAPE *aShape, bool aPermitDiagonal ) const; BreakoutList ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
BreakoutList computeBreakouts( int aWidth, const PNS_ITEM *aItem, bool aPermitDiagonal ) const; BreakoutList computeBreakouts( int aWidth, const PNS_ITEM* aItem,
bool aPermitDiagonal ) const;
int smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd, int aEndVertex ); int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex );
PNS_ITEM *findPadOrVia ( int aLayer, int aNet, const VECTOR2I& aP) const; PNS_ITEM* findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const;
SHAPE_INDEX_LIST<PNS_ITEM *> m_cache; SHAPE_INDEX_LIST<PNS_ITEM*> m_cache;
typedef boost::unordered_map<PNS_ITEM*, CachedItem> CachedItemTags; typedef boost::unordered_map<PNS_ITEM*, CachedItem> CachedItemTags;
CachedItemTags m_cacheTags; CachedItemTags m_cacheTags;
PNS_NODE *m_world; PNS_NODE* m_world;
int m_collisionKindMask; int m_collisionKindMask;
int m_effortLevel; int m_effortLevel;
bool m_keepPostures; bool m_keepPostures;
}; };
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -3,20 +3,21 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_ROUTER_H #ifndef __PNS_ROUTER_H
#define __PNS_ROUTER_H #define __PNS_ROUTER_H
@ -48,150 +49,146 @@ class PNS_CLEARANCE_FUNC;
class VIEW_GROUP; class VIEW_GROUP;
namespace KiGfx { namespace KiGfx {
class VIEW; class VIEW;
class VIEW_GROUP; class VIEW_GROUP;
}; };
/** /**
* Class PNS_ROUTER * Class PNS_ROUTER
* *
* Main router class. * Main router class.
*/ */
class PNS_ROUTER { class PNS_ROUTER
{
private: private:
enum RouterState { enum RouterState
IDLE, {
START_ROUTING, IDLE,
ROUTE_TRACK, START_ROUTING,
FINISH_TRACK ROUTE_TRACK,
}; FINISH_TRACK
};
public: public:
PNS_ROUTER();
~PNS_ROUTER();
PNS_ROUTER (); static PNS_ROUTER* GetInstance();
~PNS_ROUTER ();
static PNS_ROUTER *GetInstance(); void ClearWorld();
void SetBoard( BOARD* aBoard );
void SyncWorld();
void ClearWorld(); void SetView( KiGfx::VIEW* aView );
void SetBoard( BOARD *aBoard );
void SyncWorld();
void SetView(KiGfx::VIEW *aView); bool RoutingInProgress() const;
void StartRouting( const VECTOR2I& aP, PNS_ITEM* aItem );
void Move( const VECTOR2I& aP, PNS_ITEM* aItem );
bool FixRoute( const VECTOR2I& aP, PNS_ITEM* aItem );
bool RoutingInProgress() const; void StopRouting();
void StartRouting(const VECTOR2I& aP, PNS_ITEM *aItem);
void Move(const VECTOR2I& aP, PNS_ITEM *aItem);
bool FixRoute(const VECTOR2I& aP, PNS_ITEM *aItem);
void StopRouting(); const VECTOR2I GetCurrentEnd() const;
const VECTOR2I GetCurrentEnd() const; int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const;
int GetClearance(const PNS_ITEM* a, const PNS_ITEM *b ) const; PNS_NODE* GetWorld() const
{
return m_world;
}
PNS_NODE* GetWorld() const void FlipPosture();
{
return m_world;
}
void FlipPosture(); void DisplayItem( const PNS_ITEM* aItem, bool aIsHead = false );
void DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType = 0, int aWidth = 0 );
void DisplayItem ( const PNS_ITEM *aItem, bool aIsHead = false ); void DisplayDebugBox( const BOX2I& aBox, int aType = 0, int aWidth = 0 );
void DisplayDebugLine ( const SHAPE_LINE_CHAIN &aLine, int aType = 0, int aWidth = 0);
void DisplayDebugBox ( const BOX2I& aBox, int aType = 0, int aWidth = 0);
void EraseView ( );
void SwitchLayer (int layer );
int GetCurrentLayer() const { return m_currentLayer; }
void ToggleViaPlacement ();
void SetCurrentWidth(int w); void EraseView();
void SetCurrentViaDiameter(int d) { m_currentViaDiameter = d;} void SwitchLayer( int layer );
void SetCurrentViaDrill(int d) { m_currentViaDrill = d;}
int GetCurrentWidth() const { return m_currentWidth; }
int GetCurrentViaDiameter() const { return m_currentViaDiameter; }
int GetCurrentViaDrill() const { return m_currentViaDrill; }
int GetCurrentNet() const { return m_currentNet; }
PNS_CLEARANCE_FUNC *GetClearanceFunc() const int GetCurrentLayer() const { return m_currentLayer; }
{ void ToggleViaPlacement();
return m_clearanceFunc;
}
bool IsPlacingVia() const void SetCurrentWidth( int w );
{
return m_placingVia;
}
void SetCurrentViaDiameter( int d ) { m_currentViaDiameter = d; }
void SetCurrentViaDrill( int d ) { m_currentViaDrill = d; }
int GetCurrentWidth() const { return m_currentWidth; }
int GetCurrentViaDiameter() const { return m_currentViaDiameter; }
int GetCurrentViaDrill() const { return m_currentViaDrill; }
int GetCurrentNet() const { return m_currentNet; }
int NextCopperLayer( bool aUp ); PNS_CLEARANCE_FUNC* GetClearanceFunc() const
{
return m_clearanceFunc;
}
//typedef boost::optional<hoverItem> optHoverItem; bool IsPlacingVia() const
{
return m_placingVia;
}
const PNS_ITEMSET QueryHoverItems(const VECTOR2I& aP); int NextCopperLayer( bool aUp );
const VECTOR2I SnapToItem( PNS_ITEM *item, VECTOR2I aP, bool& aSplitsSegment );
// typedef boost::optional<hoverItem> optHoverItem;
const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP );
const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment );
private: private:
void clearViewFlags();
// optHoverItem queryHoverItemEx(const VECTOR2I& aP);
PNS_ITEM* pickSingleItem( PNS_ITEMSET& aItems ) const; // std::vector<PNS_ITEM*> aItems) const;
void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP ); // optHoverItem& aItem);
void commitRouting( PNS_NODE* aNode );
PNS_NODE* removeLoops( PNS_NODE* aNode, PNS_SEGMENT* aLatestSeg );
PNS_NODE* removeLoops( PNS_NODE* aNode, PNS_LINE* aNewLine );
PNS_VIA* checkLoneVia( PNS_JOINT* aJoint ) const;
void clearViewFlags(); PNS_ITEM* syncPad( D_PAD* aPad );
PNS_ITEM* syncTrack( TRACK* aTrack );
//optHoverItem queryHoverItemEx(const VECTOR2I& aP); PNS_ITEM* syncVia( SEGVIA* aVia );
PNS_ITEM *pickSingleItem ( PNS_ITEMSET &aItems ) const; //std::vector<PNS_ITEM*> aItems) const;
void splitAdjacentSegments(PNS_NODE *aNode, PNS_ITEM *aSeg, const VECTOR2I& aP ); //optHoverItem& aItem);
void commitRouting ( PNS_NODE *aNode );
PNS_NODE *removeLoops ( PNS_NODE *aNode, PNS_SEGMENT *aLatestSeg );
PNS_NODE *removeLoops ( PNS_NODE *aNode, PNS_LINE *aNewLine );
PNS_VIA *checkLoneVia ( PNS_JOINT* aJoint ) const;
PNS_ITEM *syncPad( D_PAD *aPad ); void commitPad( PNS_SOLID* aPad );
PNS_ITEM *syncTrack( TRACK *aTrack ); void commitSegment( PNS_SEGMENT* aTrack );
PNS_ITEM *syncVia( SEGVIA *aVia ); void commitVia( PNS_VIA* aVia );
void commitPad( PNS_SOLID *aPad ); void highlightCurrent( bool enabled );
void commitSegment( PNS_SEGMENT *aTrack );
void commitVia( PNS_VIA *aVia );
void highlightCurrent( bool enabled ); int m_currentLayer;
int m_currentNet;
int m_currentWidth;
int m_currentViaDiameter;
int m_currentViaDrill;
bool m_start_diagonal;
int m_currentLayer; RouterState m_state;
int m_currentNet;
int m_currentWidth;
int m_currentViaDiameter;
int m_currentViaDrill;
bool m_start_diagonal; BOARD* m_board;
PNS_NODE* m_world;
PNS_LINE_PLACER* m_placer;
RouterState m_state; KiGfx::VIEW* m_view;
KiGfx::VIEW_GROUP* m_previewItems;
BOARD *m_board; VECTOR2I m_currentEnd;
PNS_NODE *m_world; VECTOR2I m_currentStart;
PNS_LINE_PLACER *m_placer; VECTOR2I m_originalStart;
bool m_placingVia;
bool m_startsOnVia;
KiGfx::VIEW *m_view; // optHoverItem m_startItem, m_endItem;
KiGfx::VIEW_GROUP *m_previewItems;
VECTOR2I m_currentEnd; PNS_ROUTING_SETTINGS m_settings;
VECTOR2I m_currentStart; PNS_CLEARANCE_FUNC* m_clearanceFunc;
VECTOR2I m_originalStart;
bool m_placingVia;
bool m_startsOnVia;
// optHoverItem m_startItem, m_endItem;
PNS_ROUTING_SETTINGS m_settings;
PNS_CLEARANCE_FUNC *m_clearanceFunc;
boost::unordered_set<BOARD_ITEM *> m_hiddenItems;
boost::unordered_set<BOARD_ITEM*> m_hiddenItems;
}; };
#endif #endif

View File

@ -3,50 +3,51 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_ROUTER_SETTINGS #ifndef __PNS_ROUTER_SETTINGS
#define __PNS_ROUTER_SETTINGS #define __PNS_ROUTER_SETTINGS
///> Routing modes ///> Routing modes
enum PNS_MODE { enum PNS_MODE
RM_Ignore = 0, ///> Ignore collisions {
RM_Shove, ///> Only shove RM_Ignore = 0, ///> Ignore collisions
RM_Walkaround, ///> Only walkaround RM_Shove, ///> Only shove
RM_Smart ///> Guess what's better RM_Walkaround, ///> Only walkaround
RM_Smart ///> Guess what's better
}; };
class PNS_ROUTING_SETTINGS class PNS_ROUTING_SETTINGS
{ {
public: public:
PNS_MODE m_routingMode; PNS_MODE m_routingMode;
bool m_removeLoops; bool m_removeLoops;
bool m_smartPads; bool m_smartPads;
bool m_suggestEnding; bool m_suggestEnding;
bool m_shoveOnRequest; bool m_shoveOnRequest;
bool m_changePostures; bool m_changePostures;
bool m_followMouse; bool m_followMouse;
int m_lineWidth; int m_lineWidth;
int m_viaDiameter; int m_viaDiameter;
int m_viaDrill; int m_viaDrill;
int m_preferredLayer; int m_preferredLayer;
int m_walkaroundIterationLimit; int m_walkaroundIterationLimit;
int m_shoveIterationLimit; int m_shoveIterationLimit;
}; };
#endif #endif

View File

@ -3,21 +3,21 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __PNS_SEGMENT_H #ifndef __PNS_SEGMENT_H
#define __PNS_SEGMENT_H #define __PNS_SEGMENT_H
@ -32,88 +32,94 @@
class PNS_NODE; class PNS_NODE;
class PNS_SEGMENT : public PNS_ITEM { class PNS_SEGMENT : public PNS_ITEM
{
public: public:
PNS_SEGMENT (): PNS_SEGMENT() :
PNS_ITEM(SEGMENT) PNS_ITEM( SEGMENT )
{}; {};
PNS_SEGMENT (const SEG& aSeg, int aNet): PNS_SEGMENT( const SEG& aSeg, int aNet ) :
PNS_ITEM(SEGMENT) PNS_ITEM( SEGMENT )
{ {
m_net = aNet; m_net = aNet;
m_shape.Clear(); m_shape.Clear();
m_shape.Append(aSeg.a); m_shape.Append( aSeg.a );
m_shape.Append(aSeg.b); m_shape.Append( aSeg.b );
}; };
PNS_SEGMENT (const PNS_LINE &aParentLine, const SEG& aSeg):
PNS_ITEM(SEGMENT)
{
m_net = aParentLine.GetNet();
m_layers = aParentLine.GetLayers();
m_width = aParentLine.GetWidth();
m_shape.Clear();
m_shape.Append(aSeg.a);
m_shape.Append(aSeg.b);
};
PNS_SEGMENT *Clone() const; PNS_SEGMENT( const PNS_LINE& aParentLine, const SEG& aSeg ) :
PNS_ITEM( SEGMENT )
const SHAPE* GetShape() const { {
return static_cast<const SHAPE *>(&m_shape); m_net = aParentLine.GetNet();
} m_layers = aParentLine.GetLayers();
m_width = aParentLine.GetWidth();
m_shape.Clear();
m_shape.Append( aSeg.a );
m_shape.Append( aSeg.b );
};
void SetLayer (int aLayer)
{
SetLayers (PNS_LAYERSET ( aLayer ));
}
int GetLayer() const PNS_SEGMENT* Clone() const;
{
return GetLayers().Start();
}
const SHAPE_LINE_CHAIN& GetCLine() const const SHAPE* GetShape() const
{ {
return m_shape; return static_cast<const SHAPE*>( &m_shape );
} }
void SetWidth( int aWidth ) void SetLayer( int aLayer )
{ {
m_width = aWidth; SetLayers( PNS_LAYERSET( aLayer ) );
} }
int GetWidth() const { int GetLayer() const
return m_width; {
} return GetLayers().Start();
}
const SEG GetSeg() const {
assert(m_shape.PointCount() >= 1);
if(m_shape.PointCount() == 1)
return SEG(m_shape.CPoint(0), m_shape.CPoint(0));
return SEG(m_shape.CPoint(0), m_shape.CPoint(1));
}
void SetEnds ( const VECTOR2I& a, const VECTOR2I& b) const SHAPE_LINE_CHAIN& GetCLine() const
{ {
m_shape.Clear(); return m_shape;
m_shape.Append(a); }
m_shape.Append(b);
}
void SwapEnds() void SetWidth( int aWidth )
{ {
m_shape = m_shape.Reverse(); m_width = aWidth;
} }
const SHAPE_LINE_CHAIN Hull(int aClearance, int aWalkaroundThickness) const; int GetWidth() const
{
return m_width;
}
const SEG GetSeg() const
{
assert( m_shape.PointCount() >= 1 );
if( m_shape.PointCount() == 1 )
return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 0 ) );
return SEG( m_shape.CPoint( 0 ), m_shape.CPoint( 1 ) );
}
void SetEnds( const VECTOR2I& a, const VECTOR2I& b )
{
m_shape.Clear();
m_shape.Append( a );
m_shape.Append( b );
}
void SwapEnds()
{
m_shape = m_shape.Reverse();
}
const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const;
private: private:
SHAPE_LINE_CHAIN m_shape;
SHAPE_LINE_CHAIN m_shape; int m_width;
int m_width;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -37,433 +37,458 @@
using namespace std; using namespace std;
PNS_SHOVE::PNS_SHOVE( PNS_NODE *aWorld ) PNS_SHOVE::PNS_SHOVE( PNS_NODE* aWorld )
{ {
m_root = aWorld; m_root = aWorld;
m_iterLimit = 100; m_iterLimit = 100;
}; };
PNS_SHOVE::~PNS_SHOVE() PNS_SHOVE::~PNS_SHOVE()
{ {
} }
struct range {
range()
{
min_v = max_v = -1;
}
void add ( int x ) struct range
{ {
if(min_v < 0) min_v = x; range()
if(max_v < 0) max_v = x; {
min_v = max_v = -1;
}
if(x < min_v) void add( int x )
min_v = x; {
else if (x > max_v) if( min_v < 0 ) min_v = x;
max_v = x;
}
int start() if( max_v < 0 ) max_v = x;
{
return min_v;
}
int end() if( x < min_v )
{ min_v = x;
return max_v; else if( x > max_v )
} max_v = x;
}
int min_v, max_v; int start()
{
return min_v;
}
int end()
{
return max_v;
}
int min_v, max_v;
}; };
// fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm. // fixme: this is damn f***ing inefficient. And fails much too often due to broken direction finding algorithm.
bool PNS_SHOVE::tryShove(PNS_NODE *aNode, PNS_LINE *aHead, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult, bool aInvertWinding ) bool PNS_SHOVE::tryShove( PNS_NODE* aNode, PNS_LINE* aHead, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding )
{ {
const SHAPE_LINE_CHAIN &head = aHead->GetCLine(); const SHAPE_LINE_CHAIN& head = aHead->GetCLine();
bool cw = false; bool cw = false;
int i; int i;
if(aHead->EndsWithVia() && !aHead->GetLayers().Overlaps(aObstacle->GetLayers())) if( aHead->EndsWithVia() && !aHead->GetLayers().Overlaps( aObstacle->GetLayers() ) )
{ {
int clearance = aNode->GetClearance(aHead, aObstacle); int clearance = aNode->GetClearance( aHead, aObstacle );
SHAPE_LINE_CHAIN hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 ); SHAPE_LINE_CHAIN hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 );
//SHAPE_LINE_CHAIN path_pre, path_walk_cw, path_walk_ccw, path_post; // SHAPE_LINE_CHAIN path_pre, path_walk_cw, path_walk_ccw, path_post;
SHAPE_LINE_CHAIN path_cw, path_ccw, *path; SHAPE_LINE_CHAIN path_cw, path_ccw, * path;
aObstacle->NewWalkaround(hull, path_cw, true); aObstacle->NewWalkaround( hull, path_cw, true );
aObstacle->NewWalkaround(hull, path_ccw, false); aObstacle->NewWalkaround( hull, path_ccw, false );
path = path_ccw.Length() < path_cw.Length() ? &path_ccw : &path_cw; path = path_ccw.Length() < path_cw.Length() ? &path_ccw : &path_cw;
aResult->SetShape(*path); aResult->SetShape( *path );
//PNSDisplayDebugLine (*path, 5); // PNSDisplayDebugLine (*path, 5);
if(!aResult->Is45Degree()) if( !aResult->Is45Degree() )
{ {
//printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str()); // printf("polyset non-45\npoly %s\nendpolyset\n", aResult->GetCLine().Format().c_str());
} }
/*... special case for vias? */
return !aNode->CheckColliding(aResult, aHead); /*... special case for vias? */
}
int ns = head.SegmentCount(); return !aNode->CheckColliding( aResult, aHead );
if(aHead->EndsWithVia()) }
ns ++;
for(i = 0; i < head.SegmentCount(); i++) int ns = head.SegmentCount();
{
const PNS_SEGMENT hs (*aHead, head.CSegment(i)); if( aHead->EndsWithVia() )
ns++;
for( i = 0; i < head.SegmentCount(); i++ )
{
const PNS_SEGMENT hs( *aHead, head.CSegment( i ) );
if( aNode->CheckColliding( &hs, aObstacle ) )
{
VECTOR2I v1 = hs.GetSeg().b - hs.GetSeg().a;
VECTOR2I v2 = aObstacleSeg.GetSeg().b - aObstacleSeg.GetSeg().a;
if(aNode->CheckColliding(&hs, aObstacle)) VECTOR2I::extended_type det = v1.Cross( v2 );
{
VECTOR2I v1 = hs.GetSeg().b - hs.GetSeg().a;
VECTOR2I v2 = aObstacleSeg.GetSeg().b - aObstacleSeg.GetSeg().a;
VECTOR2I::extended_type det = v1.Cross(v2);
if(det > 0) if( det > 0 )
cw = true; cw = true;
else else
cw = false; cw = false;
break;
}
}
if(aInvertWinding) break;
{ }
if(cw) }
cw = false;
else
cw = true;
}
PNS_LINE shoved (*aObstacle); if( aInvertWinding )
{
if( cw )
cw = false;
else
cw = true;
}
int clearance = aNode->GetClearance(aHead, aObstacle); PNS_LINE shoved( *aObstacle );
range r; int clearance = aNode->GetClearance( aHead, aObstacle );
for(i = 0; i < ns; i++) range r;
{
SHAPE_LINE_CHAIN hull;
if(i < head.SegmentCount())
{
const PNS_SEGMENT hs (*aHead, head.CSegment(i));
hull = hs.Hull( clearance, 0 );
} else
hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2);
SHAPE_LINE_CHAIN path_pre, path_walk, path_post, tmp;
SHAPE_LINE_CHAIN path_pre2, path_walk2, path_post2;
//shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw); for( i = 0; i < ns; i++ )
shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw); {
SHAPE_LINE_CHAIN hull;
/*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 ) if( i < head.SegmentCount() )
{ {
TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str()); const PNS_SEGMENT hs( *aHead, head.CSegment( i ) );
TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str()); hull = hs.Hull( clearance, 0 );
}*/ }
else
hull = aHead->GetVia().Hull( clearance - aObstacle->GetWidth() / 2 );
tmp = shoved.GetCLine(); SHAPE_LINE_CHAIN path_pre, path_walk, path_post, tmp;
if(path_walk.SegmentCount()) SHAPE_LINE_CHAIN path_pre2, path_walk2, path_post2;
r.add(i);
path_pre.Append(path_walk); // shoved.NewWalkaround(hull, path_pre, path_walk, path_post, cw);
path_pre.Append(path_post); shoved.NewWalkaround( hull, path_pre, path_walk, path_post, cw );
path_pre.Simplify();
shoved.SetShape(path_pre);
// shoved.SetAffectedRange ( start, end );
*aResult = shoved;
if(!aResult->Is45Degree())
{
//TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str());
}
}
TRACE(2, "CW %d affectedRange %d-%d [total %d]", (cw?1:0) % r.start() % r.end() % ns); /*if(path_pre != path_pre2 || path_post != path_post2 || path_walk != path_walk2 )
* {
* TRACE(5, "polyset orig\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre.Format().c_str() % path_walk.Format().c_str() % path_post.Format().c_str());
* TRACE(5, "polyset err\npoly %s\npoly %s\npoly %s\nendpolyset\n", path_pre2.Format().c_str() % path_walk2.Format().c_str() % path_post2.Format().c_str());
* }*/
return !aNode->CheckColliding(aResult, aHead); tmp = shoved.GetCLine();
if( path_walk.SegmentCount() )
r.add( i );
path_pre.Append( path_walk );
path_pre.Append( path_post );
path_pre.Simplify();
shoved.SetShape( path_pre );
// shoved.SetAffectedRange ( start, end );
*aResult = shoved;
if( !aResult->Is45Degree() )
{
// TRACE(5, "polyset non-45\npoly %s\npoly %s\npoly %s\nendpolyset\n", tmp.Format().c_str() % hull.Format().c_str() % aResult->GetCLine().Format().c_str());
}
}
TRACE( 2, "CW %d affectedRange %d-%d [total %d]", (cw ? 1 : 0) % r.start() % r.end() % ns );
return !aNode->CheckColliding( aResult, aHead );
} }
PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult )
PNS_SHOVE::ShoveStatus PNS_SHOVE::shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent,
PNS_LINE* aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult )
{ {
bool rv = tryShove(aNode, aCurrent, aObstacle, aObstacleSeg, aResult, false); bool rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, false );
if( !rv ) if( !rv )
rv = tryShove(aNode, aCurrent, aObstacle, aObstacleSeg, aResult, true); rv = tryShove( aNode, aCurrent, aObstacle, aObstacleSeg, aResult, true );
if( !rv ) if( !rv )
{ {
TRACEn(2, "Shove failed" ); TRACEn( 2, "Shove failed" );
return SH_INCOMPLETE; return SH_INCOMPLETE;
} }
aResult->GetLine().Simplify(); aResult->GetLine().Simplify();
const SHAPE_LINE_CHAIN& sh_shoved = aResult->GetCLine(); const SHAPE_LINE_CHAIN& sh_shoved = aResult->GetCLine();
const SHAPE_LINE_CHAIN& sh_orig = aObstacle->GetCLine(); const SHAPE_LINE_CHAIN& sh_orig = aObstacle->GetCLine();
if(sh_shoved.SegmentCount() > 1 && sh_shoved.CPoint(0) == sh_orig.CPoint(0) && sh_shoved.CPoint(-1) == sh_orig.CPoint(-1) ) if( sh_shoved.SegmentCount() > 1 && sh_shoved.CPoint( 0 ) == sh_orig.CPoint( 0 )
return SH_OK; && sh_shoved.CPoint( -1 ) == sh_orig.CPoint( -1 ) )
else if (!sh_shoved.SegmentCount()) return SH_OK;
return SH_NULL; else if( !sh_shoved.SegmentCount() )
else return SH_NULL;
return SH_INCOMPLETE; else
return SH_INCOMPLETE;
} }
bool PNS_SHOVE::reduceSpringback( PNS_LINE *aHead )
{
bool rv = false;
while(!m_nodeStack.empty())
{
SpringbackTag st_stack = m_nodeStack.back();
bool tail_ok = true;
if(!st_stack.node->CheckColliding(aHead) && tail_ok)
{
rv = true;
delete st_stack.node;
m_nodeStack.pop_back();
} else
break;
}
return rv; bool PNS_SHOVE::reduceSpringback( PNS_LINE* aHead )
{
bool rv = false;
while( !m_nodeStack.empty() )
{
SpringbackTag st_stack = m_nodeStack.back();
bool tail_ok = true;
if( !st_stack.node->CheckColliding( aHead ) && tail_ok )
{
rv = true;
delete st_stack.node;
m_nodeStack.pop_back();
}
else
break;
}
return rv;
} }
bool PNS_SHOVE::pushSpringback( PNS_NODE *aNode, PNS_LINE *aHead, const PNS_COST_ESTIMATOR& aCost )
bool PNS_SHOVE::pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost )
{ {
BOX2I headBB = aHead->GetCLine().BBox(); BOX2I headBB = aHead->GetCLine().BBox();
SpringbackTag st; SpringbackTag st;
st.node = aNode; st.node = aNode;
st.cost = aCost; st.cost = aCost;
st.length = std::max(headBB.GetWidth(), headBB.GetHeight());; st.length = std::max( headBB.GetWidth(), headBB.GetHeight() );;
m_nodeStack.push_back(st); m_nodeStack.push_back( st );
return true; return true;
} }
const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const const PNS_COST_ESTIMATOR PNS_SHOVE::TotalCost() const
{ {
if(m_nodeStack.empty()) if( m_nodeStack.empty() )
return PNS_COST_ESTIMATOR(); return PNS_COST_ESTIMATOR();
else else
return m_nodeStack.back().cost; return m_nodeStack.back().cost;
} }
PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines(PNS_LINE* aCurrentHead)
PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead )
{ {
stack <PNS_LINE *> lineStack; stack <PNS_LINE*> lineStack;
PNS_NODE *node, *parent; PNS_NODE* node, * parent;
PNS_VIA *headVia = NULL; PNS_VIA* headVia = NULL;
bool fail = false; bool fail = false;
int iter = 0; int iter = 0;
PNS_LINE *head = aCurrentHead->Clone(); PNS_LINE* head = aCurrentHead->Clone();
reduceSpringback(aCurrentHead); reduceSpringback( aCurrentHead );
parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node; parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().node;
node = parent->Branch(); node = parent->Branch();
lineStack.push(head); lineStack.push( head );
//node->Add(tail); // node->Add(tail);
node->Add(head); node->Add( head );
if(head->EndsWithVia()) if( head->EndsWithVia() )
{ {
headVia = head->GetVia().Clone(); headVia = head->GetVia().Clone();
node->Add( headVia ); node->Add( headVia );
} }
PNS_OPTIMIZER optimizer (node); PNS_OPTIMIZER optimizer( node );
optimizer.SetEffortLevel (PNS_OPTIMIZER::MERGE_SEGMENTS | PNS_OPTIMIZER::SMART_PADS); optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_SEGMENTS | PNS_OPTIMIZER::SMART_PADS );
optimizer.SetCollisionMask( -1 ); optimizer.SetCollisionMask( -1 );
PNS_NODE::OptObstacle nearest; PNS_NODE::OptObstacle nearest;
optimizer.CacheStaticItem(head); optimizer.CacheStaticItem( head );
if(headVia)
optimizer.CacheStaticItem(headVia);
TRACE(1, "ShoveStart [root: %d jts, node: %d jts]", m_root->JointCount() % node->JointCount()); if( headVia )
optimizer.CacheStaticItem( headVia );
//PNS_ITEM *lastWalkSolid = NULL;
prof_counter totalRealTime;
TRACE( 1, "ShoveStart [root: %d jts, node: %d jts]", m_root->JointCount() %
node->JointCount() );
wxLongLong t_start = wxGetLocalTimeMillis(); // PNS_ITEM *lastWalkSolid = NULL;
prof_counter totalRealTime;
while(!lineStack.empty()) wxLongLong t_start = wxGetLocalTimeMillis();
{
wxLongLong t_cur = wxGetLocalTimeMillis(); while( !lineStack.empty() )
{
wxLongLong t_cur = wxGetLocalTimeMillis();
if ((t_cur - t_start).ToLong() > ShoveTimeLimit) if( (t_cur - t_start).ToLong() > ShoveTimeLimit )
{ {
fail = true; fail = true;
break; break;
} }
iter++; iter++;
if(iter > m_iterLimit)
{
fail = true;
break;
}
PNS_LINE *currentLine = lineStack.top();
prof_start( &totalRealTime, false ); if( iter > m_iterLimit )
nearest = node->NearestObstacle(currentLine, PNS_ITEM::ANY); {
prof_end( &totalRealTime ); fail = true;
break;
}
TRACE(2,"t-nearestObstacle %lld us", (totalRealTime.value )); PNS_LINE* currentLine = lineStack.top();
if(!nearest) prof_start( &totalRealTime, false );
{ nearest = node->NearestObstacle( currentLine, PNS_ITEM::ANY );
if(lineStack.size() > 1) prof_end( &totalRealTime );
{
PNS_LINE *original = lineStack.top();
PNS_LINE optimized;
int r_start, r_end;
original->GetAffectedRange(r_start, r_end); TRACE( 2, "t-nearestObstacle %lld us", (totalRealTime.value ) );
TRACE(1, "Iter %d optimize-line [range %d-%d, total %d]", iter % r_start % r_end % original->GetCLine().PointCount() ); if( !nearest )
//lastWalkSolid = NULL; {
prof_start( &totalRealTime, false ); if( lineStack.size() > 1 )
{
PNS_LINE* original = lineStack.top();
PNS_LINE optimized;
int r_start, r_end;
if( optimizer.Optimize(original, &optimized) ) original->GetAffectedRange( r_start, r_end );
{
node->Remove(original);
optimizer.CacheRemove(original);
node->Add(&optimized);
if(original->BelongsTo(node)) TRACE( 1, "Iter %d optimize-line [range %d-%d, total %d]",
delete original; iter % r_start % r_end % original->GetCLine().PointCount() );
} // lastWalkSolid = NULL;
prof_end( &totalRealTime ); prof_start( &totalRealTime, false );
TRACE(2,"t-optimizeObstacle %lld us", (totalRealTime.value )); if( optimizer.Optimize( original, &optimized ) )
{
node->Remove( original );
optimizer.CacheRemove( original );
node->Add( &optimized );
} if( original->BelongsTo( node ) )
lineStack.pop(); delete original;
} else { }
switch(nearest->item->GetKind()) prof_end( &totalRealTime );
{
case PNS_ITEM::SEGMENT:
{
TRACE(1, "Iter %d shove-line", iter );
PNS_SEGMENT *pseg = static_cast<PNS_SEGMENT*>(nearest->item); TRACE( 2, "t-optimizeObstacle %lld us", (totalRealTime.value ) );
PNS_LINE *collidingLine = node->AssembleLine(pseg); }
PNS_LINE *shovedLine = collidingLine->CloneProperties();
prof_start( &totalRealTime, false );
ShoveStatus st = shoveSingleLine(node, currentLine, collidingLine, *pseg, shovedLine);
prof_end( &totalRealTime );
TRACE(2,"t-shoveSingle %lld us", (totalRealTime.value )); lineStack.pop();
}
else
{
switch( nearest->item->GetKind() )
{
case PNS_ITEM::SEGMENT:
{
TRACE( 1, "Iter %d shove-line", iter );
if(st == SH_OK) PNS_SEGMENT* pseg = static_cast<PNS_SEGMENT*>(nearest->item);
{ PNS_LINE* collidingLine = node->AssembleLine( pseg );
node->Replace(collidingLine, shovedLine); PNS_LINE* shovedLine = collidingLine->CloneProperties();
if(collidingLine->BelongsTo( node )) prof_start( &totalRealTime, false );
delete collidingLine; ShoveStatus st = shoveSingleLine( node, currentLine, collidingLine,
*pseg, shovedLine );
prof_end( &totalRealTime );
optimizer.CacheRemove(collidingLine); TRACE( 2, "t-shoveSingle %lld us", (totalRealTime.value ) );
lineStack.push( shovedLine );
} else
fail = true;
//lastWalkSolid = NULL;
break; if( st == SH_OK )
} // case SEGMENT {
node->Replace( collidingLine, shovedLine );
case PNS_ITEM::SOLID: if( collidingLine->BelongsTo( node ) )
case PNS_ITEM::VIA: delete collidingLine;
{
TRACE(1, "Iter %d walkaround-solid [%p]", iter % nearest->item ); optimizer.CacheRemove( collidingLine );
lineStack.push( shovedLine );
if(lineStack.size() == 1) }
{ else
fail = true; fail = true;
break;
} // lastWalkSolid = NULL;
break;
} // case SEGMENT
case PNS_ITEM::SOLID:
case PNS_ITEM::VIA:
{
TRACE( 1, "Iter %d walkaround-solid [%p]", iter % nearest->item );
if( lineStack.size() == 1 )
{
fail = true;
break;
}
/* if(lastWalkSolid == nearest->item) /* if(lastWalkSolid == nearest->item)
{ * {
fail = true; * fail = true;
break; * break;
}*/ * }*/
PNS_WALKAROUND walkaround (node); PNS_WALKAROUND walkaround( node );
PNS_LINE *walkaroundLine = currentLine->CloneProperties(); PNS_LINE* walkaroundLine = currentLine->CloneProperties();
walkaround.SetSolidsOnly(true); walkaround.SetSolidsOnly( true );
walkaround.SetSingleDirection(true); walkaround.SetSingleDirection( true );
prof_start( &totalRealTime, false );
walkaround.Route(*currentLine, *walkaroundLine, false);
prof_end( &totalRealTime );
TRACE(2,"t-walkSolid %lld us", (totalRealTime.value )); prof_start( &totalRealTime, false );
walkaround.Route( *currentLine, *walkaroundLine, false );
prof_end( &totalRealTime );
TRACE( 2, "t-walkSolid %lld us", (totalRealTime.value ) );
node->Replace(currentLine, walkaroundLine); node->Replace( currentLine, walkaroundLine );
if(currentLine->BelongsTo( node )) if( currentLine->BelongsTo( node ) )
delete currentLine; delete currentLine;
optimizer.CacheRemove(currentLine); optimizer.CacheRemove( currentLine );
lineStack.top() = walkaroundLine; lineStack.top() = walkaroundLine;
//lastWalkSolid = nearest->item; // lastWalkSolid = nearest->item;
break; break;
} }
default:
break;
} // switch
if(fail)
break;
}
}
node->Remove(head);
delete head;
if(headVia)
{
node->Remove(headVia);
delete headVia;
}
TRACE(1, "Shove status : %s after %d iterations" , (fail ? "FAILED" : "OK") % iter ); default:
if(!fail) break;
{ } // switch
pushSpringback(node, aCurrentHead, PNS_COST_ESTIMATOR());
return SH_OK; if( fail )
} else { break;
delete node; }
return SH_INCOMPLETE; }
}
node->Remove( head );
delete head;
if( headVia )
{
node->Remove( headVia );
delete headVia;
}
TRACE( 1, "Shove status : %s after %d iterations", (fail ? "FAILED" : "OK") % iter );
if( !fail )
{
pushSpringback( node, aCurrentHead, PNS_COST_ESTIMATOR() );
return SH_OK;
}
else
{
delete node;
return SH_INCOMPLETE;
}
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -30,53 +30,57 @@ class PNS_LINE;
class PNS_NODE; class PNS_NODE;
class PNS_ROUTER; class PNS_ROUTER;
class PNS_SHOVE { class PNS_SHOVE
{
public:
PNS_SHOVE( PNS_NODE* aWorld );
~PNS_SHOVE();
public: enum ShoveStatus
PNS_SHOVE(PNS_NODE *aWorld); {
~PNS_SHOVE(); SH_OK = 0,
SH_NULL,
SH_INCOMPLETE
};
enum ShoveStatus { ShoveStatus ShoveLines( PNS_LINE* aCurrentHead );
SH_OK = 0,
SH_NULL,
SH_INCOMPLETE
};
ShoveStatus ShoveLines(PNS_LINE* aCurrentHead); PNS_NODE* GetCurrentNode()
{
return m_nodeStack.empty() ? m_root : m_nodeStack.back().node;
}
PNS_NODE *GetCurrentNode() const PNS_COST_ESTIMATOR TotalCost() const;
{
return m_nodeStack.empty() ? m_root : m_nodeStack.back().node;
}
const PNS_COST_ESTIMATOR TotalCost() const; void Reset();
void KillChildNodes();
void Reset(); private:
void KillChildNodes(); static const int ShoveTimeLimit = 3000;
private: bool tryShove( PNS_NODE* aWorld, PNS_LINE* aTrack, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding );
static const int ShoveTimeLimit = 3000; ShoveStatus shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, PNS_LINE* aObstacle,
PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult );
bool tryShove(PNS_NODE *aWorld, PNS_LINE *aTrack, PNS_LINE * aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult, bool aInvertWinding ); bool reduceSpringback( PNS_LINE* aHead );
bool pushSpringback( PNS_NODE* aNode, PNS_LINE* aHead, const PNS_COST_ESTIMATOR& aCost );
ShoveStatus shoveSingleLine(PNS_NODE *aNode, PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_SEGMENT& aObstacleSeg, PNS_LINE *aResult ); struct SpringbackTag
{
int64_t length;
int segments;
VECTOR2I p;
PNS_NODE* node;
PNS_COST_ESTIMATOR cost;
};
bool reduceSpringback( PNS_LINE *aHead ); std::vector<SpringbackTag> m_nodeStack;
bool pushSpringback( PNS_NODE *aNode, PNS_LINE *aHead, const PNS_COST_ESTIMATOR& aCost ); PNS_NODE* m_root;
PNS_NODE* m_currentNode;
struct SpringbackTag { int m_iterLimit;
int64_t length;
int segments;
VECTOR2I p;
PNS_NODE *node;
PNS_COST_ESTIMATOR cost;
};
std::vector<SpringbackTag> m_nodeStack;
PNS_NODE *m_root;
PNS_NODE *m_currentNode;
int m_iterLimit;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -28,37 +28,36 @@
#include "pns_solid.h" #include "pns_solid.h"
#include "pns_utils.h" #include "pns_utils.h"
const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness) const const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness ) const
{ {
switch(m_shape->Type()) switch( m_shape->Type() )
{ {
case SH_RECT: case SH_RECT:
{ {
SHAPE_RECT *rect = static_cast<SHAPE_RECT*> (m_shape); SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape );
return OctagonalHull( rect->GetPosition(), return OctagonalHull( rect->GetPosition(), rect->GetSize(),
rect->GetSize(), aClearance + 1, 0.2 * aClearance );
aClearance + 1, }
0.2 * aClearance );
}
case SH_CIRCLE: case SH_CIRCLE:
{ {
SHAPE_CIRCLE *circle = static_cast<SHAPE_CIRCLE*> (m_shape); SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
int r = circle->GetRadius(); int r = circle->GetRadius();
return OctagonalHull( circle->GetCenter() - VECTOR2I(r, r), return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
VECTOR2I(2 * r, 2 * r), aClearance + 1, 0.52 * (r + aClearance) );
aClearance + 1, }
0.52 * (r + aClearance) );
}
default:
break;
}
return SHAPE_LINE_CHAIN(); default:
break;
}
return SHAPE_LINE_CHAIN();
} }
PNS_ITEM *PNS_SOLID::Clone() const
PNS_ITEM* PNS_SOLID::Clone() const
{ {
// solids are never cloned as the shove algorithm never moves them // solids are never cloned as the shove algorithm never moves them
assert(false); assert( false );
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -29,41 +29,42 @@
#include "pns_item.h" #include "pns_item.h"
class PNS_SOLID : public PNS_ITEM { class PNS_SOLID : public PNS_ITEM
{
public: public:
PNS_SOLID() : PNS_ITEM(SOLID) PNS_SOLID() : PNS_ITEM( SOLID )
{ {
m_movable = false; m_movable = false;
m_shape = NULL; m_shape = NULL;
} }
PNS_ITEM *Clone() const;
const SHAPE* GetShape() const { return m_shape; }
const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const; PNS_ITEM* Clone() const;
void SetShape( SHAPE* shape) const SHAPE* GetShape() const { return m_shape; }
{
if(m_shape)
delete m_shape;
m_shape = shape;
}
const VECTOR2I& GetCenter() const const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const;
{
return m_center;
}
void SetCenter( const VECTOR2I& aCenter ) void SetShape( SHAPE* shape )
{ {
m_center = aCenter; if( m_shape )
} delete m_shape;
m_shape = shape;
}
const VECTOR2I& GetCenter() const
{
return m_center;
}
void SetCenter( const VECTOR2I& aCenter )
{
m_center = aCenter;
}
private: private:
VECTOR2I m_center;
VECTOR2I m_center; SHAPE* m_shape;
SHAPE* m_shape;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -22,21 +22,24 @@
#include "pns_line.h" #include "pns_line.h"
#include "pns_router.h" #include "pns_router.h"
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I& aP0, const VECTOR2I& aSize, int aClearance, int aChamfer) const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0,
const VECTOR2I& aSize,
int aClearance,
int aChamfer )
{ {
SHAPE_LINE_CHAIN s; SHAPE_LINE_CHAIN s;
s.SetClosed( true ); s.SetClosed( true );
s.Append(aP0.x - aClearance , aP0.y - aClearance + aChamfer); s.Append( aP0.x - aClearance, aP0.y - aClearance + aChamfer );
s.Append(aP0.x - aClearance + aChamfer, aP0.y - aClearance); s.Append( aP0.x - aClearance + aChamfer, aP0.y - aClearance );
s.Append(aP0.x + aSize.x + aClearance - aChamfer, aP0.y - aClearance); s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y - aClearance );
s.Append(aP0.x + aSize.x + aClearance, aP0.y - aClearance + aChamfer); s.Append( aP0.x + aSize.x + aClearance, aP0.y - aClearance + aChamfer );
s.Append(aP0.x + aSize.x + aClearance, aP0.y + aSize.y + aClearance - aChamfer); s.Append( aP0.x + aSize.x + aClearance, aP0.y + aSize.y + aClearance - aChamfer );
s.Append(aP0.x + aSize.x + aClearance - aChamfer, aP0.y + aSize.y + aClearance); s.Append( aP0.x + aSize.x + aClearance - aChamfer, aP0.y + aSize.y + aClearance );
s.Append(aP0.x - aClearance + aChamfer, aP0.y + aSize.y + aClearance); s.Append( aP0.x - aClearance + aChamfer, aP0.y + aSize.y + aClearance );
s.Append(aP0.x - aClearance, aP0.y + aSize.y + aClearance - aChamfer); s.Append( aP0.x - aClearance, aP0.y + aSize.y + aClearance - aChamfer );
return s; return s;
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -24,10 +24,10 @@
#include <math/vector2d.h> #include <math/vector2d.h>
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
/** Various utility functions */ /** 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 #endif // __PNS_UTILS_H

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -26,123 +26,136 @@
static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force ) static bool Circle2Circle( VECTOR2I p1, VECTOR2I p2, int r1, int r2, VECTOR2I& force )
{ {
int mindist = r1 + r2;
VECTOR2I delta = p2 - p1;
int dist = delta.EuclideanNorm();
int mindist = r1 + r2; if( dist >= mindist )
VECTOR2I delta = p2 - p1; return false;
int dist = delta.EuclideanNorm();
force = delta.Resize( abs( mindist - dist ) + 1 );
if(dist >= mindist) return true;
return false;
force = delta.Resize(abs(mindist - dist) + 1);
return true;
}; };
static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force ) static bool Rect2Circle( VECTOR2I rp0, VECTOR2I rsize, VECTOR2I cc, int cr, VECTOR2I& force )
{ {
VECTOR2I vts[] = { VECTOR2I(rp0.x, rp0.y), VECTOR2I vts[] =
VECTOR2I(rp0.x, rp0.y + rsize.y), {
VECTOR2I(rp0.x + rsize.x, rp0.y + rsize.y), VECTOR2I( rp0.x, rp0.y ),
VECTOR2I(rp0.x + rsize.x, rp0.y), VECTOR2I( rp0.x, rp0.y + rsize.y ),
VECTOR2I(rp0.x, rp0.y) }; VECTOR2I( rp0.x + rsize.x, rp0.y + rsize.y ),
VECTOR2I( rp0.x + rsize.x, rp0.y ),
VECTOR2I( rp0.x, rp0.y )
};
int dist = INT_MAX; int dist = INT_MAX;
VECTOR2I nearest; VECTOR2I nearest;
for (int i = 0; i < 4; i++) for( int i = 0; i < 4; i++ )
{ {
SEG s(vts[i], vts[i+1]); SEG s( vts[i], vts[i + 1] );
VECTOR2I pn = s.NearestPoint( cc );
int d = (pn - cc).EuclideanNorm(); VECTOR2I pn = s.NearestPoint( cc );
if( d < dist )
{
nearest = pn;
dist = d;
}
}
bool inside = cc.x >= rp0.x && cc.x <= (rp0.x + rsize.x) int d = (pn - cc).EuclideanNorm();
&& cc.y >= rp0.y && cc.y <= (rp0.y + rsize.y);
VECTOR2I delta = cc - nearest; if( d < dist )
{
nearest = pn;
dist = d;
}
}
if(dist >= cr && !inside) bool inside = cc.x >= rp0.x && cc.x <= (rp0.x + rsize.x)
return false; && cc.y >= rp0.y && cc.y <= (rp0.y + rsize.y);
if(inside) VECTOR2I delta = cc - nearest;
force = -delta.Resize(abs(cr + dist) + 1);
else
force = delta.Resize(abs(cr - dist) + 1);
return true; if( dist >= cr && !inside )
return false;
if( inside )
force = -delta.Resize( abs( cr + dist ) + 1 );
else
force = delta.Resize( abs( cr - dist ) + 1 );
return true;
}; };
static bool ShPushoutForce ( const SHAPE *shape, VECTOR2I p, int r, VECTOR2I& force, int clearance) static bool ShPushoutForce( const SHAPE* shape, VECTOR2I p, int r, VECTOR2I& force, int clearance )
{ {
switch(shape->Type()) switch( shape->Type() )
{ {
case SH_CIRCLE: case SH_CIRCLE:
{ {
const SHAPE_CIRCLE *cir = static_cast<const SHAPE_CIRCLE*>(shape); const SHAPE_CIRCLE* cir = static_cast<const SHAPE_CIRCLE*>(shape);
return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force ); return Circle2Circle( cir->GetCenter(), p, cir->GetRadius(), r + clearance + 1, force );
} }
case SH_RECT:
{
const SHAPE_RECT *rect = static_cast<const SHAPE_RECT*>(shape);
return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force );
}
default:
return false;
} case SH_RECT:
return false; {
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(shape);
return Rect2Circle( rect->GetPosition(), rect->GetSize(), p, r + clearance + 1, force );
}
default:
return false;
}
return false;
} }
bool PNS_VIA::PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR2I& aForce, bool aSolidsOnly, int aMaxIterations) bool PNS_VIA::PushoutForce( PNS_NODE* aNode,
const VECTOR2I& aDirection,
VECTOR2I& aForce,
bool aSolidsOnly,
int aMaxIterations )
{ {
int iter = 0; int iter = 0;
PNS_VIA mv ( *this); PNS_VIA mv( *this );
VECTOR2I force, totalForce; VECTOR2I force, totalForce;
while(iter < aMaxIterations) while( iter < aMaxIterations )
{ {
PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY); PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv,
aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
if(!obs)
break;
int clearance = aNode->GetClearance(obs->item, &mv); if( !obs )
break;
if(iter > 10) int clearance = aNode->GetClearance( obs->item, &mv );
{
VECTOR2I l = - aDirection.Resize(m_diameter / 4);
totalForce += l;
mv.SetPos(mv.GetPos() + l);
}
if( ShPushoutForce(obs->item->GetShape(), mv.GetPos(), mv.GetDiameter() / 2, force, clearance) ) if( iter > 10 )
{ {
totalForce += force; VECTOR2I l = -aDirection.Resize( m_diameter / 4 );
mv.SetPos(mv.GetPos() + force); totalForce += l;
} mv.SetPos( mv.GetPos() + l );
}
if( ShPushoutForce( obs->item->GetShape(), mv.GetPos(), mv.GetDiameter() / 2, force,
clearance ) )
{
totalForce += force;
mv.SetPos( mv.GetPos() + force );
}
iter++; iter++;
} }
if(iter == aMaxIterations) if( iter == aMaxIterations )
return false; return false;
aForce = totalForce; aForce = totalForce;
return true; return true;
} }
const SHAPE_LINE_CHAIN PNS_VIA::Hull(int aClearance, int aWalkaroundThickness) const
const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const
{ {
return OctagonalHull( m_pos - VECTOR2I(m_diameter/2, m_diameter/2), VECTOR2I(m_diameter, m_diameter), aClearance + 1, (2*aClearance + m_diameter) * 0.26); return OctagonalHull( m_pos -
VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter,
m_diameter ), aClearance + 1, (2 * aClearance + m_diameter) * 0.26 );
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -28,91 +28,96 @@
class PNS_NODE; class PNS_NODE;
class PNS_VIA : public PNS_ITEM class PNS_VIA : public PNS_ITEM
{ {
public: public:
PNS_VIA( ): PNS_VIA() :
PNS_ITEM (VIA) {}; PNS_ITEM( VIA ) {};
PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1) : PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) :
PNS_ITEM (VIA) { PNS_ITEM( VIA )
SetNet(aNet); {
SetLayers(aLayers); SetNet( aNet );
m_pos = aPos; SetLayers( aLayers );
m_diameter = aDiameter; m_pos = aPos;
m_shape = SHAPE_CIRCLE(aPos, aDiameter/2); m_diameter = aDiameter;
}; m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 );
};
PNS_VIA(const PNS_VIA& b) : PNS_ITEM(VIA) PNS_VIA( const PNS_VIA& b ) : PNS_ITEM( VIA )
{ {
SetNet(b.GetNet()); SetNet( b.GetNet() );
SetLayers(b.GetLayers()); SetLayers( b.GetLayers() );
m_pos = b.m_pos; m_pos = b.m_pos;
m_diameter = b.m_diameter; m_diameter = b.m_diameter;
m_shape = SHAPE_CIRCLE(m_pos, m_diameter/2); m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 );
} }
const VECTOR2I& GetPos() const const VECTOR2I& GetPos() const
{ {
return m_pos; return m_pos;
} }
void SetPos( const VECTOR2I& aPos ) void SetPos( const VECTOR2I& aPos )
{ {
m_pos = aPos; m_pos = aPos;
m_shape.SetCenter(aPos); m_shape.SetCenter( aPos );
} }
int GetDiameter() const int GetDiameter() const
{ {
return m_diameter; return m_diameter;
} }
void SetDiameter(int aDiameter) void SetDiameter( int aDiameter )
{ {
m_diameter = aDiameter; m_diameter = aDiameter;
m_shape.SetRadius(m_diameter/2); m_shape.SetRadius( m_diameter / 2 );
} }
int GetDrill() const int GetDrill() const
{ {
return m_drill; return m_drill;
} }
void SetDrill(int aDrill) void SetDrill( int aDrill )
{ {
m_drill = aDrill; m_drill = aDrill;
} }
bool PushoutForce ( PNS_NODE *aNode, const VECTOR2I &aDirection, VECTOR2I& aForce, bool aSolidsOnly = true, int aMaxIterations = 10); bool PushoutForce( PNS_NODE* aNode,
const VECTOR2I& aDirection,
VECTOR2I& aForce,
bool aSolidsOnly = true,
int aMaxIterations = 10 );
const SHAPE *GetShape() const const SHAPE* GetShape() const
{ {
return &m_shape; return &m_shape;
} }
PNS_VIA *Clone() const PNS_VIA* Clone() const
{ {
PNS_VIA *v = new PNS_VIA(); PNS_VIA* v = new PNS_VIA();
v->SetNet(GetNet()); v->SetNet( GetNet() );
v->SetLayers(GetLayers()); v->SetLayers( GetLayers() );
v->m_pos = m_pos; v->m_pos = m_pos;
v->m_diameter = m_diameter; v->m_diameter = m_diameter;
v->m_shape = SHAPE_CIRCLE(m_pos, m_diameter/2); v->m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 );
return v;
}
const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const; return v;
}
private: const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const;
int m_diameter; private:
int m_drill;
VECTOR2I m_pos; int m_diameter;
SHAPE_CIRCLE m_shape; int m_drill;
VECTOR2I m_pos;
SHAPE_CIRCLE m_shape;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -35,187 +35,197 @@ using boost::optional;
void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath ) void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
{ {
m_iteration = 0; m_iteration = 0;
m_iteration_limit = 50; m_iteration_limit = 50;
} }
PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle(const PNS_LINE& aPath) PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
{ {
return m_world->NearestObstacle ( &aPath, m_solids_only ? (PNS_ITEM::SOLID | PNS_ITEM::VIA) : PNS_ITEM::ANY ); return m_world->NearestObstacle( &aPath,
m_solids_only ? (PNS_ITEM::SOLID | PNS_ITEM::VIA) : PNS_ITEM::ANY );
} }
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep(PNS_LINE& aPath, bool aWindingDirection) PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
bool aWindingDirection )
{ {
optional<PNS_OBSTACLE>& current_obs = aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1]; optional<PNS_OBSTACLE>& current_obs =
bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1]; aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1];
bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1];
if(!current_obs)
return DONE;
SHAPE_LINE_CHAIN path_pre[2], path_walk[2], path_post[2]; if( !current_obs )
return DONE;
VECTOR2I last = aPath.GetCLine().CPoint(-1); SHAPE_LINE_CHAIN path_pre[2], path_walk[2], path_post[2];
if((current_obs->hull).PointInside(last)) VECTOR2I last = aPath.GetCLine().CPoint( -1 );
{
m_recursiveBlockageCount ++;
if(m_recursiveBlockageCount < 3) if( ( current_obs->hull ).PointInside( last ) )
aPath.GetLine().Append( current_obs->hull.NearestPoint(last) ); {
else { m_recursiveBlockageCount++;
aPath = aPath.ClipToNearestObstacle(m_world);
return STUCK;
}
}
aPath.NewWalkaround(current_obs->hull, path_pre[0], path_walk[0], path_post[0], aWindingDirection); if( m_recursiveBlockageCount < 3 )
aPath.NewWalkaround(current_obs->hull, path_pre[1], path_walk[1], path_post[1], !aWindingDirection); aPath.GetLine().Append( current_obs->hull.NearestPoint( last ) );
else
{
aPath = aPath.ClipToNearestObstacle( m_world );
return STUCK;
}
}
aPath.NewWalkaround( current_obs->hull, path_pre[0], path_walk[0],
path_post[0], aWindingDirection );
aPath.NewWalkaround( current_obs->hull, path_pre[1], path_walk[1],
path_post[1], !aWindingDirection );
int len_pre = path_walk[0].Length(); int len_pre = path_walk[0].Length();
int len_alt = path_walk[1].Length(); int len_alt = path_walk[1].Length();
PNS_LINE walk_path (aPath, path_walk[1]);
bool alt_collides = m_world->CheckColliding(&walk_path, m_solids_only ? PNS_ITEM::SOLID : PNS_ITEM::ANY);
SHAPE_LINE_CHAIN pnew; PNS_LINE walk_path( aPath, path_walk[1] );
if(!m_forceSingleDirection && len_alt < len_pre && !alt_collides && !prev_recursive) bool alt_collides = m_world->CheckColliding( &walk_path,
{ m_solids_only ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
pnew = path_pre[1];
pnew.Append(path_walk[1]);
pnew.Append(path_post[1]);
current_obs = nearestObstacle(PNS_LINE(aPath, path_post[1]));
prev_recursive = false;
} else {
pnew = path_pre[0];
pnew.Append(path_walk[0]);
pnew.Append(path_post[0]);
current_obs = nearestObstacle(PNS_LINE(aPath, path_walk[0]));
if(!current_obs) SHAPE_LINE_CHAIN pnew;
{
prev_recursive = false;
current_obs = nearestObstacle(PNS_LINE(aPath, path_post[0]));
} else
prev_recursive = true;
}
if( !m_forceSingleDirection && len_alt < len_pre && !alt_collides && !prev_recursive )
pnew.Simplify(); {
aPath.SetShape(pnew); pnew = path_pre[1];
pnew.Append( path_walk[1] );
pnew.Append( path_post[1] );
return IN_PROGRESS; current_obs = nearestObstacle( PNS_LINE( aPath, path_post[1] ) );
prev_recursive = false;
}
else
{
pnew = path_pre[0];
pnew.Append( path_walk[0] );
pnew.Append( path_post[0] );
current_obs = nearestObstacle( PNS_LINE( aPath, path_walk[0] ) );
if( !current_obs )
{
prev_recursive = false;
current_obs = nearestObstacle( PNS_LINE( aPath, path_post[0] ) );
}
else
prev_recursive = true;
}
pnew.Simplify();
aPath.SetShape( pnew );
return IN_PROGRESS;
} }
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize )
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath,
PNS_LINE& aWalkPath,
bool aOptimize )
{ {
PNS_LINE path_cw(aInitialPath), path_ccw(aInitialPath); PNS_LINE path_cw( aInitialPath ), path_ccw( aInitialPath );
WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS; WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
SHAPE_LINE_CHAIN best_path; SHAPE_LINE_CHAIN best_path;
start(aInitialPath); start( aInitialPath );
m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle(aInitialPath); m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath );
m_recursiveBlockageCount = 0; m_recursiveBlockageCount = 0;
aWalkPath = aInitialPath; aWalkPath = aInitialPath;
while(m_iteration < m_iteration_limit) while( m_iteration < m_iteration_limit )
{ {
if(s_cw != STUCK) if( s_cw != STUCK )
s_cw = singleStep(path_cw, true); s_cw = singleStep( path_cw, true );
if(s_ccw != STUCK)
s_ccw = singleStep(path_ccw, false);
if((s_cw == DONE && s_ccw == DONE) || (s_cw == STUCK && s_ccw == STUCK)) if( s_ccw != STUCK )
{ s_ccw = singleStep( path_ccw, false );
int len_cw = path_cw.GetCLine().Length();
int len_ccw = path_ccw.GetCLine().Length(); if( ( s_cw == DONE && s_ccw == DONE ) || ( s_cw == STUCK && s_ccw == STUCK ) )
{
int len_cw = path_cw.GetCLine().Length();
int len_ccw = path_ccw.GetCLine().Length();
if( m_forceLongerPath )
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
else
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
break;
}
else if( s_cw == DONE && !m_forceLongerPath )
{
aWalkPath = path_cw;
break;
}
else if( s_ccw == DONE && !m_forceLongerPath )
{
aWalkPath = path_ccw;
break;
}
m_iteration++;
}
if( m_iteration == m_iteration_limit )
{
int len_cw = path_cw.GetCLine().Length();
int len_ccw = path_ccw.GetCLine().Length();
if(m_forceLongerPath) if( m_forceLongerPath )
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
else else
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw); aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
}
break; if( m_cursorApproachMode )
} else if(s_cw == DONE && !m_forceLongerPath) { {
aWalkPath = path_cw; // int len_cw = path_cw.GetCLine().Length();
break; // int len_ccw = path_ccw.GetCLine().Length();
} else if (s_ccw == DONE && !m_forceLongerPath) { bool found = false;
aWalkPath = path_ccw;
break;
}
SHAPE_LINE_CHAIN l = aWalkPath.GetCLine();
m_iteration++; for( int i = 0; i < l.SegmentCount(); i++ )
} {
const SEG s = l.Segment( i );
if(m_iteration == m_iteration_limit) VECTOR2I nearest = s.NearestPoint( m_cursorPos );
{ VECTOR2I::extended_type dist_a = (s.a - m_cursorPos).SquaredEuclideanNorm();
int len_cw = path_cw.GetCLine().Length(); VECTOR2I::extended_type dist_b = (s.b - m_cursorPos).SquaredEuclideanNorm();
int len_ccw = path_ccw.GetCLine().Length(); VECTOR2I::extended_type dist_n = (nearest - m_cursorPos).SquaredEuclideanNorm();
if( dist_n <= dist_a && dist_n < dist_b )
{
// PNSDisplayDebugLine(l, 3);
l.Remove( i + 1, -1 );
l.Append( nearest );
l.Simplify();
found = true;
break;
}
}
if(m_forceLongerPath) if( found )
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw); {
else aWalkPath = aInitialPath;
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw); aWalkPath.SetShape( l );
}
}
} aWalkPath.SetWorld( m_world );
aWalkPath.GetLine().Simplify();
if(m_cursorApproachMode) WalkaroundStatus st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK;
{
//int len_cw = path_cw.GetCLine().Length();
//int len_ccw = path_ccw.GetCLine().Length();
bool found = false;
SHAPE_LINE_CHAIN l = aWalkPath.GetCLine(); if( aOptimize && st == DONE )
PNS_OPTIMIZER::Optimize( &aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world );
return st;
for(int i = 0; i < l.SegmentCount(); i++)
{
const SEG s = l.Segment(i);
VECTOR2I nearest = s.NearestPoint(m_cursorPos);
VECTOR2I::extended_type dist_a = (s.a - m_cursorPos).SquaredEuclideanNorm();
VECTOR2I::extended_type dist_b = (s.b - m_cursorPos).SquaredEuclideanNorm();
VECTOR2I::extended_type dist_n = (nearest - m_cursorPos).SquaredEuclideanNorm();
if(dist_n <= dist_a && dist_n < dist_b)
{
//PNSDisplayDebugLine(l, 3);
l.Remove(i + 1, -1);
l.Append( nearest );
l.Simplify();
found = true;
break;
}
}
if(found)
{
aWalkPath = aInitialPath;
aWalkPath.SetShape(l);
}
}
aWalkPath.SetWorld(m_world);
aWalkPath.GetLine().Simplify();
WalkaroundStatus st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK;
if(aOptimize && st == DONE)
PNS_OPTIMIZER::Optimize(&aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world);
return st;
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -24,76 +24,75 @@
#include "pns_line.h" #include "pns_line.h"
#include "pns_node.h" #include "pns_node.h"
class PNS_WALKAROUND { class PNS_WALKAROUND
{
static const int DefaultIterationLimit = 50; static const int DefaultIterationLimit = 50;
public:
PNS_WALKAROUND( PNS_NODE* aWorld ) :
m_world( aWorld ), m_iteration_limit( DefaultIterationLimit )
{
m_forceSingleDirection = false;
m_forceLongerPath = false;
m_cursorApproachMode = false;
};
~PNS_WALKAROUND() {};
enum WalkaroundStatus
{
IN_PROGRESS = 0,
DONE,
STUCK
};
public: void SetWorld( PNS_NODE* aNode )
PNS_WALKAROUND( PNS_NODE *aWorld ): {
m_world(aWorld), m_iteration_limit(DefaultIterationLimit) { m_world = aNode;
m_forceSingleDirection = false; }
m_forceLongerPath = false;
m_cursorApproachMode = false;
};
~PNS_WALKAROUND() {};
enum WalkaroundStatus { void SetIterationLimit( const int aIterLimit )
IN_PROGRESS = 0, {
DONE, m_iteration_limit = aIterLimit;
STUCK }
};
void SetWorld ( PNS_NODE *aNode ) void SetSolidsOnly( bool aSolidsOnly )
{ {
m_world = aNode; m_solids_only = aSolidsOnly;
} }
void SetIterationLimit( const int aIterLimit ) void SetSingleDirection( bool aForceSingleDirection )
{ {
m_iteration_limit = aIterLimit; m_forceSingleDirection = aForceSingleDirection;
} m_forceLongerPath = true;
}
void SetSolidsOnly ( bool aSolidsOnly ) void SetApproachCursor( bool aEnabled, const VECTOR2I& aPos )
{ {
m_solids_only = aSolidsOnly; m_cursorPos = aPos;
} m_cursorApproachMode = aEnabled;
}
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
bool aOptimize = true );
void SetSingleDirection (bool aForceSingleDirection ) private:
{ void start( const PNS_LINE& aInitialPath );
m_forceSingleDirection = aForceSingleDirection;
m_forceLongerPath = true;
}
void SetApproachCursor ( bool aEnabled, const VECTOR2I& aPos ) WalkaroundStatus singleStep( PNS_LINE& aPath, bool aWindingDirection );
{ PNS_NODE::OptObstacle nearestObstacle( const PNS_LINE& aPath );
m_cursorPos = aPos;
m_cursorApproachMode = aEnabled;
}
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, bool aOptimize = true); PNS_NODE* m_world;
private: int m_recursiveBlockageCount;
void start( const PNS_LINE& aInitialPath ); int m_iteration;
int m_iteration_limit;
WalkaroundStatus singleStep(PNS_LINE& aPath, bool aWindingDirection); bool m_solids_only;
PNS_NODE::OptObstacle nearestObstacle(const PNS_LINE& aPath); bool m_forceSingleDirection, m_forceLongerPath;
bool m_cursorApproachMode;
PNS_NODE *m_world; VECTOR2I m_cursorPos;
PNS_NODE::OptObstacle m_currentObstacle[2];
int m_recursiveBlockageCount; bool m_recursiveCollision[2];
int m_iteration;
int m_iteration_limit;
bool m_solids_only;
bool m_forceSingleDirection, m_forceLongerPath;
bool m_cursorApproachMode;
VECTOR2I m_cursorPos;
PNS_NODE::OptObstacle m_currentObstacle[2];
bool m_recursiveCollision[2];
}; };
#endif // __PNS_WALKAROUND_H #endif // __PNS_WALKAROUND_H

View File

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

View File

@ -3,21 +3,21 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#include <gal/color4d.h> #include <gal/color4d.h>
#include "class_track.h" #include "class_track.h"
@ -31,167 +31,200 @@
using namespace KiGfx; using namespace KiGfx;
ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM *aItem, VIEW_GROUP *aParent ) ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aParent ) :
: EDA_ITEM( NOT_USED ) EDA_ITEM( NOT_USED )
{ {
m_Flags = 0; m_Flags = 0;
m_parent = aParent; m_parent = aParent;
if(aItem)
Update(aItem); if( aItem )
} Update( aItem );
}
ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM() ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
{ {
} }
void ROUTER_PREVIEW_ITEM::Update(const PNS_ITEM *aItem)
void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem )
{ {
m_layer = aItem->GetLayers().Start(); m_layer = aItem->GetLayers().Start();
m_color = getLayerColor( m_layer );
m_color.a = 0.8;
m_color = getLayerColor( m_layer ); switch( aItem->GetKind() )
m_color.a = 0.8; {
case PNS_ITEM::LINE:
switch(aItem->GetKind()) m_type = PR_LINE;
{ m_width = static_cast<const PNS_LINE*>(aItem)->GetWidth();
case PNS_ITEM::LINE: m_line = *static_cast<const SHAPE_LINE_CHAIN*>( aItem->GetShape() );
m_type = PR_LINE; break;
m_width = static_cast<const PNS_LINE *>(aItem)->GetWidth();
m_line = * static_cast<const SHAPE_LINE_CHAIN *>(aItem->GetShape());
break;
case PNS_ITEM::SEGMENT: case PNS_ITEM::SEGMENT:
m_type = PR_LINE; m_type = PR_LINE;
m_width = static_cast<const PNS_SEGMENT *>(aItem)->GetWidth(); m_width = static_cast<const PNS_SEGMENT*>(aItem)->GetWidth();
m_line = * static_cast<const SHAPE_LINE_CHAIN *>(aItem->GetShape()); m_line = *static_cast<const SHAPE_LINE_CHAIN*>( aItem->GetShape() );
break; break;
case PNS_ITEM::VIA: case PNS_ITEM::VIA:
m_type = PR_VIA; m_type = PR_VIA;
m_color = COLOR4D(0.7, 0.7, 0.7, 0.8); m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
m_width = static_cast<const PNS_VIA *>(aItem)->GetDiameter(); m_width = static_cast<const PNS_VIA*>(aItem)->GetDiameter();
m_viaCenter = static_cast<const PNS_VIA *>(aItem)->GetPos(); m_viaCenter = static_cast<const PNS_VIA*>(aItem)->GetPos();
break; break;
default: default:
break; break;
} }
ViewSetVisible(true); ViewSetVisible( true );
ViewUpdate(GEOMETRY | APPEARANCE); ViewUpdate( GEOMETRY | APPEARANCE );
} }
void ROUTER_PREVIEW_ITEM::MarkAsHead( )
void ROUTER_PREVIEW_ITEM::MarkAsHead()
{ {
if(m_type != PR_VIA) if( m_type != PR_VIA )
m_color.Saturate(1.0); m_color.Saturate( 1.0 );
} }
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
{ {
BOX2I bbox; BOX2I bbox;
switch(m_type) switch( m_type )
{ {
case PR_LINE: case PR_LINE:
bbox = m_line.BBox(); bbox = m_line.BBox();
bbox.Inflate( m_width / 2); bbox.Inflate( m_width / 2 );
return bbox; return bbox;
case PR_VIA:
bbox = BOX2I( m_viaCenter, VECTOR2I(0, 0)); case PR_VIA:
bbox.Inflate( m_width / 2); bbox = BOX2I( m_viaCenter, VECTOR2I( 0, 0 ) );
return bbox; bbox.Inflate( m_width / 2 );
default: return bbox;
break;
} default:
return bbox; break;
}
return bbox;
} }
void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KiGfx::GAL* aGal ) const void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KiGfx::GAL* aGal ) const
{ {
switch( m_type ) switch( m_type )
{ {
case PR_LINE: case PR_LINE:
aGal->SetLayerDepth( -100.0 );
aGal->SetLineWidth( m_width );
aGal->SetStrokeColor( m_color );
aGal->SetIsStroke( true );
aGal->SetIsFill( false );
aGal->SetLayerDepth(-100.0); for( int s = 0; s < m_line.SegmentCount(); s++ )
aGal->SetLineWidth(m_width); aGal->DrawLine( m_line.CSegment( s ).a, m_line.CSegment( s ).b );
aGal->SetStrokeColor(m_color);
aGal->SetIsStroke(true); if( m_line.IsClosed() )
aGal->SetIsFill(false); aGal->DrawLine( m_line.CSegment( -1 ).b, m_line.CSegment( 0 ).a );
for(int s= 0 ; s < m_line.SegmentCount(); s++) break;
aGal->DrawLine(m_line.CSegment(s).a, m_line.CSegment(s).b);
if(m_line.IsClosed()) case PR_VIA:
aGal->DrawLine(m_line.CSegment(-1).b, m_line.CSegment(0).a); aGal->SetLayerDepth( -101.0 );
break; aGal->SetIsStroke( false );
case PR_VIA: aGal->SetIsFill( true );
aGal->SetFillColor( m_color );
aGal->SetLayerDepth(-101.0); aGal->DrawCircle( m_viaCenter, m_width / 2 );
aGal->SetIsStroke(false); break;
aGal->SetIsFill(true);
aGal->SetFillColor(m_color); default:
aGal->DrawCircle(m_viaCenter, m_width / 2); break;
break; }
default:
break;
}
} }
void ROUTER_PREVIEW_ITEM::DebugLine ( const SHAPE_LINE_CHAIN& aLine, int aWidth , int aStyle ) void ROUTER_PREVIEW_ITEM::DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
{ {
#if 0 #if 0
m_line = aLine; m_line = aLine;
m_width = aWidth; m_width = aWidth;
m_color = assignColor(aStyle); m_color = assignColor( aStyle );
m_type = PR_LINE;
ViewUpdate(GEOMETRY | APPEARANCE); m_type = PR_LINE;
ViewUpdate( GEOMETRY | APPEARANCE );
#endif #endif
} }
void ROUTER_PREVIEW_ITEM::DebugBox ( const BOX2I& aBox, int aStyle )
void ROUTER_PREVIEW_ITEM::DebugBox( const BOX2I& aBox, int aStyle )
{ {
#if 0 #if 0
assert(false); assert( false );
m_line.Clear(); m_line.Clear();
m_line.Append( aBox.GetX(), aBox.GetY() ); m_line.Append( aBox.GetX(), aBox.GetY() );
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()); m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight() );
m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight()); m_line.Append( aBox.GetX() + aBox.GetWidth(), aBox.GetY() + aBox.GetHeight() );
m_line.Append( aBox.GetX(), aBox.GetY() + aBox.GetHeight()); m_line.Append( aBox.GetX(), aBox.GetY() + aBox.GetHeight() );
m_line.SetClosed(true); m_line.SetClosed( true );
m_width = 20000; m_width = 20000;
m_color = assignColor(aStyle); m_color = assignColor( aStyle );
m_type = PR_LINE; m_type = PR_LINE;
ViewUpdate(GEOMETRY | APPEARANCE); ViewUpdate( GEOMETRY | APPEARANCE );
#endif #endif
} }
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor (int layer ) const
{
//assert (m_view != NULL);
PCB_RENDER_SETTINGS *settings = static_cast <PCB_RENDER_SETTINGS*> (m_parent -> GetView() -> GetPainter() -> GetSettings());
return settings->GetLayerColor(layer); const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
{
// assert (m_view != NULL);
PCB_RENDER_SETTINGS* settings =
static_cast <PCB_RENDER_SETTINGS*> ( m_parent->GetView()->GetPainter()->GetSettings() );
return settings->GetLayerColor( aLayer );
} }
const COLOR4D ROUTER_PREVIEW_ITEM::assignColor ( int style ) const const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
{ {
COLOR4D color; COLOR4D color;
switch(style)
{ switch( aStyle )
case 0: color =COLOR4D(0, 1, 0, 1);break; {
case 1: color =COLOR4D(1, 0, 0, 0.3);break; case 0:
case 2: color =COLOR4D(1, 0.5, 0.5, 1);break; color = COLOR4D( 0, 1, 0, 1 ); break;
case 3: color =COLOR4D(0, 0, 1, 1);break;
case 4: color =COLOR4D(1, 1, 1, 1); break; case 1:
case 5: color =COLOR4D(1, 1, 0, 1); break; color = COLOR4D( 1, 0, 0, 0.3 ); break;
case 6: color =COLOR4D(0, 1, 1, 1); break;
case 32: color =COLOR4D(0, 0, 1, 0.5); break; case 2:
default: break; color = COLOR4D( 1, 0.5, 0.5, 1 ); break;
}
return color; case 3:
color = COLOR4D( 0, 0, 1, 1 ); break;
case 4:
color = COLOR4D( 1, 1, 1, 1 ); break;
case 5:
color = COLOR4D( 1, 1, 0, 1 ); break;
case 6:
color = COLOR4D( 0, 1, 1, 1 ); break;
case 32:
color = COLOR4D( 0, 0, 1, 0.5 ); break;
default:
break;
}
return color;
} }

View File

@ -3,21 +3,21 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __ROUTER_PREVIEW_ITEM_H #ifndef __ROUTER_PREVIEW_ITEM_H
#define __ROUTER_PREVIEW_ITEM_H #define __ROUTER_PREVIEW_ITEM_H
@ -43,61 +43,61 @@ class PNS_ROUTER;
class ROUTER_PREVIEW_ITEM : public EDA_ITEM class ROUTER_PREVIEW_ITEM : public EDA_ITEM
{ {
public: public:
enum ItemType { enum ItemType
PR_VIA, {
PR_LINE, PR_VIA,
PR_STUCK_MARKER PR_LINE,
}; PR_STUCK_MARKER
};
enum ItemFlags { enum ItemFlags
PR_SUGGESTION = 1 {
}; PR_SUGGESTION = 1
};
ROUTER_PREVIEW_ITEM( const PNS_ITEM *aItem = NULL, KiGfx::VIEW_GROUP *aParent = NULL ); ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem = NULL, KiGfx::VIEW_GROUP* aParent = NULL );
~ROUTER_PREVIEW_ITEM(); ~ROUTER_PREVIEW_ITEM();
void Update ( const PNS_ITEM *aItem);
void StuckMarker( VECTOR2I& aPosition ); void Update( const PNS_ITEM* aItem );
void DebugLine ( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 );
void DebugBox ( const BOX2I& aBox, int aStyle = 0);
void Show(int a, std::ostream& b) const {};
const BOX2I ViewBBox() const; void StuckMarker( VECTOR2I& aPosition );
void DebugLine( const SHAPE_LINE_CHAIN& aLine, int aWidth = 0, int aStyle = 0 );
void DebugBox( const BOX2I& aBox, int aStyle = 0 );
virtual void ViewDraw( int aLayer, KiGfx::GAL* aGal ) const;
virtual void ViewGetLayers( int aLayers[], int& aCount ) const
{
aLayers[0] = GP_OVERLAY;
aCount = 1;
}
void MarkAsHead( );
private: void Show( int a, std::ostream& b ) const {};
const KiGfx::COLOR4D assignColor ( int style ) const; const BOX2I ViewBBox() const;
const KiGfx::COLOR4D getLayerColor (int layer ) const;
KiGfx::VIEW_GROUP *m_parent; virtual void ViewDraw( int aLayer, KiGfx::GAL* aGal ) const;
PNS_ROUTER *m_router; virtual void ViewGetLayers( int aLayers[], int& aCount ) const
SHAPE_LINE_CHAIN m_line; {
aLayers[0] = GP_OVERLAY;
aCount = 1;
}
ItemType m_type; void MarkAsHead();
int m_style;
int m_width;
int m_layer;
KiGfx::COLOR4D m_color; private:
const KiGfx::COLOR4D assignColor( int aStyle ) const;
const KiGfx::COLOR4D getLayerColor( int aLayer ) const;
VECTOR2I m_stuckPosition; KiGfx::VIEW_GROUP* m_parent;
VECTOR2I m_viaCenter;
PNS_ROUTER* m_router;
SHAPE_LINE_CHAIN m_line;
ItemType m_type;
int m_style;
int m_width;
int m_layer;
KiGfx::COLOR4D m_color;
VECTOR2I m_stuckPosition;
VECTOR2I m_viaCenter;
}; };
#endif #endif

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -42,70 +42,73 @@ using namespace KiGfx;
using namespace std; using namespace std;
using boost::optional; using boost::optional;
static TOOL_ACTION ACT_AutoEndRoute ( "AutoEndRoute", AS_CONTEXT, 'F' ); static TOOL_ACTION ACT_AutoEndRoute( "AutoEndRoute", AS_CONTEXT, 'F' );
static TOOL_ACTION ACT_PlaceVia ( "PlaceVia", AS_CONTEXT, 'V' ); static TOOL_ACTION ACT_PlaceVia( "PlaceVia", AS_CONTEXT, 'V' );
static TOOL_ACTION ACT_OpenRouteOptions ( "OpenRouterOptions", AS_CONTEXT, 'E' ); static TOOL_ACTION ACT_OpenRouteOptions( "OpenRouterOptions", AS_CONTEXT, 'E' );
static TOOL_ACTION ACT_SwitchPosture ( "SwitchPosture", AS_CONTEXT, '/' ); static TOOL_ACTION ACT_SwitchPosture( "SwitchPosture", AS_CONTEXT, '/' );
static TOOL_ACTION ACT_EndTrack ( "SwitchPosture", AS_CONTEXT, WXK_END ); static TOOL_ACTION ACT_EndTrack( "SwitchPosture", AS_CONTEXT, WXK_END );
ROUTER_TOOL::ROUTER_TOOL() : ROUTER_TOOL::ROUTER_TOOL() :
TOOL_INTERACTIVE( "pcbnew.InteractiveRouter" ) TOOL_INTERACTIVE( "pcbnew.InteractiveRouter" )
{ {
m_router = NULL; m_router = NULL;
m_menu = new CONTEXT_MENU ; m_menu = new CONTEXT_MENU;
m_menu->SetTitle( wxT( "Interactive router") ); // fixme: not implemented yet. Sorry. m_menu->SetTitle( wxT( "Interactive router" ) ); // fixme: not implemented yet. Sorry.
m_menu->Add( wxT ("Cancel"), 0); m_menu->Add( wxT( "Cancel" ), 0 );
m_menu->Add( wxT ("New track"), 1); m_menu->Add( wxT( "New track" ), 1 );
m_menu->Add( wxT ("End track"), 2); m_menu->Add( wxT( "End track" ), 2 );
m_menu->Add( wxT ("Auto-end track"), 2); m_menu->Add( wxT( "Auto-end track" ), 2 );
m_menu->Add( wxT ("Place via"), 3); m_menu->Add( wxT( "Place via" ), 3 );
m_menu->Add( wxT ("Switch posture"), 4); m_menu->Add( wxT( "Switch posture" ), 4 );
m_menu->Add( wxT ("Routing options..."), 5); m_menu->Add( wxT( "Routing options..." ), 5 );
} }
ROUTER_TOOL::~ROUTER_TOOL() ROUTER_TOOL::~ROUTER_TOOL()
{ {
delete m_router; delete m_router;
} }
void ROUTER_TOOL::Reset() void ROUTER_TOOL::Reset()
{ {
if( m_router )
if(m_router)
delete m_router; delete m_router;
m_router = new PNS_ROUTER; m_router = new PNS_ROUTER;
TRACEn(0,"Reset"); TRACEn( 0, "Reset" );
m_router->ClearWorld(); m_router->ClearWorld();
m_router->SetBoard( getModel <BOARD> (PCB_T) ); m_router->SetBoard( getModel<BOARD>( PCB_T ) );
m_router->SyncWorld(); m_router->SyncWorld();
if(getView()) if( getView() )
m_router->SetView( getView() ); m_router->SetView( getView() );
Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) ); Go( &ROUTER_TOOL::Main, TOOL_EVENT( TC_Command, TA_Action, GetName() ) );
} }
int ROUTER_TOOL::getDefaultWidth( int aNetCode ) int ROUTER_TOOL::getDefaultWidth( int aNetCode )
{ {
int w, d1, d2; int w, d1, d2;
getNetclassDimensions( aNetCode, w, d1, d2);
getNetclassDimensions( aNetCode, w, d1, d2 );
return w; return w;
} }
void ROUTER_TOOL::getNetclassDimensions ( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill)
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth,
int& aViaDiameter, int& aViaDrill )
{ {
BOARD *board = getModel <BOARD> (PCB_T); BOARD* board = getModel<BOARD>( PCB_T );
NETCLASS* netClass = NULL; NETCLASS* netClass = NULL;
NETINFO_ITEM *ni = board->FindNet(aNetCode); NETINFO_ITEM* ni = board->FindNet( aNetCode );
if(ni) if( ni )
{ {
wxString netClassName = ni->GetClassName(); wxString netClassName = ni->GetClassName();
netClass = board->m_NetClasses.Find( netClassName ); netClass = board->m_NetClasses.Find( netClassName );
@ -113,26 +116,27 @@ void ROUTER_TOOL::getNetclassDimensions ( int aNetCode, int& aWidth, int& aViaDi
if( !netClass ) if( !netClass )
netClass = board->m_NetClasses.GetDefault(); netClass = board->m_NetClasses.GetDefault();
aWidth = netClass->GetTrackWidth(); aWidth = netClass->GetTrackWidth();
aViaDiameter = netClass->GetViaDiameter(); aViaDiameter = netClass->GetViaDiameter();
aViaDrill = netClass->GetViaDrill(); aViaDrill = netClass->GetViaDrill();
} }
PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer ) PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer )
{ {
int tl = getView()->GetTopLayer(); int tl = getView()->GetTopLayer();
if(aLayer > 0) if( aLayer > 0 )
tl = aLayer; tl = aLayer;
PNS_ITEM *picked_seg = NULL, *picked_via = NULL; PNS_ITEM* picked_seg = NULL;
PNS_ITEMSET candidates = m_router->QueryHoverItems(aWhere); PNS_ITEM* picked_via = NULL;
PNS_ITEMSET candidates = m_router->QueryHoverItems( aWhere );
BOOST_FOREACH( PNS_ITEM *item, candidates.Items() ) BOOST_FOREACH( PNS_ITEM* item, candidates.Items() )
{ {
if( !IsCopperLayer(item->GetLayers().Start()) ) if( !IsCopperLayer( item->GetLayers().Start() ) )
continue; continue;
if( item->GetParent() && !item->GetParent()->ViewIsVisible() ) if( item->GetParent() && !item->GetParent()->ViewIsVisible() )
@ -140,108 +144,116 @@ PNS_ITEM *ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
if( aNet < 0 || item->GetNet() == aNet ) if( aNet < 0 || item->GetNet() == aNet )
{ {
if( item->OfKind (PNS_ITEM::VIA | PNS_ITEM::SOLID) ) if( item->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ) )
{ {
if(item->GetLayers().Overlaps(tl) || !picked_via) if( item->GetLayers().Overlaps( tl ) || !picked_via )
picked_via = item; picked_via = item;
} else { }
if(item->GetLayers().Overlaps(tl) || !picked_seg) else
picked_seg = item; {
if( item->GetLayers().Overlaps( tl ) || !picked_seg )
picked_seg = item;
} }
} }
} }
if( DisplayOpt.ContrastModeDisplay ) if( DisplayOpt.ContrastModeDisplay )
{ {
if( picked_seg && !picked_seg->GetLayers().Overlaps(tl)) if( picked_seg && !picked_seg->GetLayers().Overlaps( tl ) )
picked_seg = NULL; picked_seg = NULL;
} }
PNS_ITEM *rv = picked_via ? picked_via : picked_seg;
if( rv && aLayer >= 0 && !rv-> GetLayers().Overlaps(aLayer) ) PNS_ITEM* rv = picked_via ? picked_via : picked_seg;
if( rv && aLayer >= 0 && !rv->GetLayers().Overlaps( aLayer ) )
rv = NULL; rv = NULL;
if(rv) if( rv )
TRACE(0, "%s, layer : %d, tl: %d", rv->GetKindStr().c_str() % rv->GetLayers().Start() % tl); TRACE( 0, "%s, layer : %d, tl: %d", rv->GetKindStr().c_str() % rv->GetLayers().Start() %
tl );
return rv; return rv;
} }
void ROUTER_TOOL::setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage, const wxString& aLowerMessage ) void ROUTER_TOOL::setMsgPanel( bool aEnabled, int aEntry,
const wxString& aUpperMessage, const wxString& aLowerMessage )
{ {
PCB_EDIT_FRAME *frame = getEditFrame<PCB_EDIT_FRAME> (); PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
if(m_panelItems.size() <= (unsigned int) entry) if( m_panelItems.size() <= (unsigned int) aEntry )
m_panelItems.resize(entry + 1); m_panelItems.resize( aEntry + 1 );
m_panelItems[entry] = MSG_PANEL_ITEM( aUpperMessage, aLowerMessage, BLACK ); m_panelItems[aEntry] = MSG_PANEL_ITEM( aUpperMessage, aLowerMessage, BLACK );
frame->SetMsgPanel(m_panelItems); frame->SetMsgPanel( m_panelItems );
} }
void ROUTER_TOOL::clearMsgPanel() void ROUTER_TOOL::clearMsgPanel()
{ {
PCB_EDIT_FRAME *frame = getEditFrame<PCB_EDIT_FRAME> (); PCB_EDIT_FRAME* frame = getEditFrame<PCB_EDIT_FRAME> ();
frame->ClearMsgPanel(); frame->ClearMsgPanel();
} }
void ROUTER_TOOL::highlightNet(bool enabled, int netcode)
void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode )
{ {
RENDER_SETTINGS *rs = getView()->GetPainter()->GetSettings(); RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings();
if(netcode >= 0 && enabled) if( aNetcode >= 0 && aEnabled )
rs->SetHighlight(true, netcode); rs->SetHighlight( true, aNetcode );
else else
rs->SetHighlight(false); rs->SetHighlight( false );
getView()->UpdateAllLayersColor(); getView()->UpdateAllLayersColor();
} }
void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
{ {
VIEW_CONTROLS *ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
int tl = getView()->GetTopLayer(); int tl = getView()->GetTopLayer();
PNS_ITEM *startItem = NULL; PNS_ITEM* startItem = NULL;
if( aEvent.IsMotion() || aEvent.IsClick() ) if( aEvent.IsMotion() || aEvent.IsClick() )
{ {
VECTOR2I p = aEvent.Position(); VECTOR2I p = aEvent.Position();
startItem = pickSingleItem(p); startItem = pickSingleItem( p );
if( startItem && startItem->GetNet() >= 0 )
if(startItem && startItem->GetNet() >= 0)
{ {
bool dummy; bool dummy;
VECTOR2I cursorPos = m_router->SnapToItem (startItem, p, dummy); VECTOR2I cursorPos = m_router->SnapToItem( startItem, p, dummy );
ctls->ForceCursorPosition(true, cursorPos); ctls->ForceCursorPosition( true, cursorPos );
m_startSnapPoint = cursorPos; m_startSnapPoint = cursorPos;
if(startItem->GetLayers().IsMultilayer())
if( startItem->GetLayers().IsMultilayer() )
m_startLayer = tl; m_startLayer = tl;
else else
m_startLayer = startItem->GetLayers().Start(); m_startLayer = startItem->GetLayers().Start();
m_startItem = startItem; m_startItem = startItem;
} else { }
else
{
m_startItem = NULL; m_startItem = NULL;
m_startSnapPoint = p; m_startSnapPoint = p;
m_startLayer = tl; m_startLayer = tl;
ctls->ForceCursorPosition(false); ctls->ForceCursorPosition( false );
} }
} }
} }
void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent ) void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
{ {
VIEW_CONTROLS *ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
VECTOR2I p = aEvent.Position(); VECTOR2I p = aEvent.Position();
int layer; int layer;
if(m_router->GetCurrentNet() < 0 || !m_startItem) if( m_router->GetCurrentNet() < 0 || !m_startItem )
{ {
m_endItem = NULL; m_endItem = NULL;
m_endSnapPoint = p; m_endSnapPoint = p;
@ -250,48 +262,53 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
bool dummy; bool dummy;
if(m_router->IsPlacingVia()) if( m_router->IsPlacingVia() )
layer = -1; layer = -1;
else else
layer = m_router->GetCurrentLayer(); layer = m_router->GetCurrentLayer();
PNS_ITEM *endItem = pickSingleItem(p, m_startItem->GetNet(), layer );
if(endItem) PNS_ITEM* endItem = pickSingleItem( p, m_startItem->GetNet(), layer );
if( endItem )
{ {
VECTOR2I cursorPos = m_router->SnapToItem (endItem, p, dummy); VECTOR2I cursorPos = m_router->SnapToItem( endItem, p, dummy );
ctls->ForceCursorPosition(true, cursorPos); ctls->ForceCursorPosition( true, cursorPos );
m_endItem = endItem; m_endItem = endItem;
m_endSnapPoint = cursorPos; m_endSnapPoint = cursorPos;
} else { }
else
{
m_endItem = NULL; m_endItem = NULL;
m_endSnapPoint = p; m_endSnapPoint = p;
ctls->ForceCursorPosition(false); ctls->ForceCursorPosition( false );
} }
if(m_endItem) if( m_endItem )
TRACE(0, "%s, layer : %d", m_endItem->GetKindStr().c_str() % m_endItem->GetLayers().Start() ); TRACE( 0, "%s, layer : %d", m_endItem->GetKindStr().c_str() %
m_endItem->GetLayers().Start() );
} }
void ROUTER_TOOL::startRouting ( )
void ROUTER_TOOL::startRouting()
{ {
VIEW_CONTROLS *ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1);
if(m_startItem && m_startItem->OfKind(PNS_ITEM::SEGMENT))
width = static_cast<PNS_SEGMENT *>(m_startItem)->GetWidth();
m_router->SetCurrentWidth(width); int width = getDefaultWidth( m_startItem ? m_startItem->GetNet() : -1 );
m_router->SwitchLayer(m_startLayer);
getEditFrame<PCB_EDIT_FRAME>() -> SetTopLayer (m_startLayer); if( m_startItem && m_startItem->OfKind( PNS_ITEM::SEGMENT ) )
width = static_cast<PNS_SEGMENT*>( m_startItem )->GetWidth();
if(m_startItem && m_startItem->GetNet() >= 0) m_router->SetCurrentWidth( width );
highlightNet(true, m_startItem->GetNet() ); m_router->SwitchLayer( m_startLayer );
getEditFrame<PCB_EDIT_FRAME>()->SetTopLayer( m_startLayer );
if( m_startItem && m_startItem->GetNet() >= 0 )
highlightNet( true, m_startItem->GetNet() );
ctls->ForceCursorPosition( false );
ctls->SetAutoPan( true );
ctls->ForceCursorPosition(false);
ctls->SetAutoPan(true);
m_router->StartRouting( m_startSnapPoint, m_startItem ); m_router->StartRouting( m_startSnapPoint, m_startItem );
m_endItem = NULL; m_endItem = NULL;
@ -299,93 +316,94 @@ void ROUTER_TOOL::startRouting ( )
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
if( evt->IsCancel() ) if( evt->IsCancel() )
break; break;
else if (evt->IsMotion()) else if( evt->IsMotion() )
{ {
updateEndItem( *evt ); updateEndItem( *evt );
m_router->Move ( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
} }
else if (evt->IsClick (MB_Left )) else if( evt->IsClick( MB_Left ) )
{ {
updateEndItem( *evt ); updateEndItem( *evt );
if(m_router->FixRoute(m_endSnapPoint, m_endItem))
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
break; break;
m_router->Move ( m_endSnapPoint, m_endItem );
} else if (evt->IsKeyUp()) m_router->Move( m_endSnapPoint, m_endItem );
{ }
else if( evt->IsKeyUp() )
{
switch( evt->KeyCode() ) switch( evt->KeyCode() )
{ {
case 'V': case 'V':
{ {
int w, diameter, drill; int w, diameter, drill;
getNetclassDimensions( m_router->GetCurrentNet(), w, diameter, drill ); getNetclassDimensions( m_router->GetCurrentNet(), w, diameter, drill );
m_router->SetCurrentViaDiameter(diameter); m_router->SetCurrentViaDiameter( diameter );
m_router->SetCurrentViaDrill(drill); m_router->SetCurrentViaDrill( drill );
m_router->ToggleViaPlacement(); m_router->ToggleViaPlacement();
getEditFrame<PCB_EDIT_FRAME>() -> SetTopLayer (m_router->GetCurrentLayer()); getEditFrame<PCB_EDIT_FRAME>()->SetTopLayer( m_router->GetCurrentLayer() );
m_router->Move ( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
break; break;
}
case '/':
m_router->FlipPosture();
break;
case '+':
case '=':
m_router->SwitchLayer ( m_router->NextCopperLayer (true) );
updateEndItem( *evt );
getEditFrame<PCB_EDIT_FRAME>() -> SetTopLayer (m_router->GetCurrentLayer());
m_router->Move ( m_endSnapPoint, m_endItem );
break;
case '-':
m_router->SwitchLayer ( m_router->NextCopperLayer (false) );
getEditFrame<PCB_EDIT_FRAME>() -> SetTopLayer (m_router->GetCurrentLayer());
m_router->Move ( m_endSnapPoint, m_endItem );
break;
} }
}
case '/':
m_router->FlipPosture();
break;
case '+':
case '=':
m_router->SwitchLayer( m_router->NextCopperLayer( true ) );
updateEndItem( *evt );
getEditFrame<PCB_EDIT_FRAME>()->SetTopLayer( m_router->GetCurrentLayer() );
m_router->Move( m_endSnapPoint, m_endItem );
break;
case '-':
m_router->SwitchLayer( m_router->NextCopperLayer( false ) );
getEditFrame<PCB_EDIT_FRAME>()->SetTopLayer( m_router->GetCurrentLayer() );
m_router->Move( m_endSnapPoint, m_endItem );
break;
}
}
} }
if(m_router->RoutingInProgress()) if( m_router->RoutingInProgress() )
m_router->StopRouting(); m_router->StopRouting();
ctls->SetAutoPan(false); ctls->SetAutoPan( false );
ctls->ForceCursorPosition(false); ctls->ForceCursorPosition( false );
highlightNet(false); highlightNet( false );
} }
int ROUTER_TOOL::Main( TOOL_EVENT& aEvent ) int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
{ {
VIEW_CONTROLS *ctls = getViewControls(); VIEW_CONTROLS* ctls = getViewControls();
//SetContextMenu ( m_menu ); // SetContextMenu ( m_menu );
//setMsgPanel(true, 0, wxT("KiRouter"), wxT("Pick an item to start routing")); // setMsgPanel(true, 0, wxT("KiRouter"), wxT("Pick an item to start routing"));
ctls->SetSnapping ( true ); ctls->SetSnapping( true );
ctls->ShowCursor( true ); ctls->ShowCursor( true );
// Main loop: keep receiving events // Main loop: keep receiving events
while( OPT_TOOL_EVENT evt = Wait() ) while( OPT_TOOL_EVENT evt = Wait() )
{ {
if( evt->IsCancel() ) if( evt->IsCancel() )
break; // Finish break; // Finish
else if( evt->IsMotion( ) ) else if( evt->IsMotion() )
updateStartItem( *evt ); updateStartItem( *evt );
else if( evt->IsClick ( MB_Left ) ) else if( evt->IsClick( MB_Left ) )
{ {
updateStartItem( *evt ); updateStartItem( *evt );
startRouting( ); startRouting();
} }
} }
// clearMsgPanel();
//clearMsgPanel();
// Restore the default settings // Restore the default settings
ctls->SetAutoPan( false ); ctls->SetAutoPan( false );
@ -394,4 +412,3 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
return 0; return 0;
} }

View File

@ -3,17 +3,17 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
@ -45,35 +45,36 @@ public:
int Main( TOOL_EVENT& aEvent ); int Main( TOOL_EVENT& aEvent );
private: private:
PNS_ITEM *pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
void setMsgPanel ( bool enabled, int entry, const wxString& aUpperMessage = wxT(""), const wxString& aLowerMessage = wxT("") ); PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
void clearMsgPanel();
int getDefaultWidth( int aNetCode ); void setMsgPanel( bool enabled, int entry, const wxString& aUpperMessage = wxT(""),
void startRouting ( ); const wxString& aLowerMessage = wxT("") );
void highlightNet(bool enabled, int netcode = -1); void clearMsgPanel();
void updateStartItem( TOOL_EVENT& aEvent ); int getDefaultWidth( int aNetCode );
void updateEndItem( TOOL_EVENT& aEvent ); void startRouting();
void highlightNet( bool enabled, int netcode = -1 );
void getNetclassDimensions ( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill); void updateStartItem( TOOL_EVENT& aEvent );
void updateEndItem( TOOL_EVENT& aEvent );
MSG_PANEL_ITEMS m_panelItems; void getNetclassDimensions( int aNetCode, int& aWidth, int& aViaDiameter, int& aViaDrill );
PNS_ROUTER *m_router; MSG_PANEL_ITEMS m_panelItems;
PNS_ITEM *m_startItem; PNS_ROUTER* m_router;
int m_startLayer;
VECTOR2I m_startSnapPoint;
PNS_ITEM *m_endItem; PNS_ITEM* m_startItem;
VECTOR2I m_endSnapPoint; int m_startLayer;
VECTOR2I m_startSnapPoint;
PNS_ITEM* m_endItem;
VECTOR2I m_endSnapPoint;
/*boost::shared_ptr<CONTEXT_MENU> m_menu;*/ /*boost::shared_ptr<CONTEXT_MENU> m_menu;*/
CONTEXT_MENU * m_menu; CONTEXT_MENU* m_menu;
}; };
#endif #endif

View File

@ -3,48 +3,45 @@
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the * under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your * Free Software Foundation, either version 3 of the License, or (at your
* option) any later version. * option) any later version.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>. * with this program. If not, see <http://www.gnu.or/licenses/>.
*/ */
#ifndef __TRACE_H #ifndef __TRACE_H
#define __TRACE_H #define __TRACE_H
#ifdef DEBUG #ifdef DEBUG
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <boost/format.hpp> #include <boost/format.hpp>
static void _trace_print(const char *funcName, int level, const std::string& msg) static void _trace_print( const char* funcName, int level, const std::string& msg )
{ {
std::cerr << "trace[" << level << "]: " << funcName << ": " << msg << std::endl; std::cerr << "trace[" << level << "]: " << funcName << ": " << msg << std::endl;
} }
#define TRACE( level, fmt, ... ) \
_trace_print( __FUNCTION__, level, (boost::format( fmt ) % __VA_ARGS__).str() );
#define TRACEn( level, msg ) \
#define TRACE(level, fmt, ...) \ _trace_print( __FUNCTION__, level, std::string( msg ) );
_trace_print(__FUNCTION__, level, (boost::format(fmt) % __VA_ARGS__).str() );
#define TRACEn(level, msg) \
_trace_print(__FUNCTION__, level, std::string(msg));
#else #else
#define TRACE(level, fmt, ...) #define TRACE( level, fmt, ... )
#define TRACEn(level, msg) #define TRACEn( level, msg )
#endif #endif