Reformatted PNS code to conform the coding policy.
This commit is contained in:
parent
ebf35fd43a
commit
ad1b138f28
|
@ -209,12 +209,12 @@ public:
|
|||
// we are more horizontal than vertical?
|
||||
if( w > h )
|
||||
{
|
||||
mp0 = VECTOR2I( (w - h) * sw, 0 ); // direction: E
|
||||
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
|
||||
mp0 = VECTOR2I( 0, sh * ( h - w ) ); // direction: N
|
||||
mp1 = VECTOR2I( sw * w, sh * w ); // direction: NE
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ public:
|
|||
pl.Append( aP1 );
|
||||
pl.Simplify();
|
||||
return pl;
|
||||
};
|
||||
}
|
||||
|
||||
bool operator==( const DIRECTION_45& aOther ) const
|
||||
{
|
||||
|
@ -275,19 +275,17 @@ public:
|
|||
{
|
||||
DIRECTION_45 l;
|
||||
|
||||
if (m_dir == UNDEFINED)
|
||||
if ( m_dir == UNDEFINED )
|
||||
return l;
|
||||
|
||||
if(m_dir == N)
|
||||
if( m_dir == N )
|
||||
l.m_dir = NW;
|
||||
else
|
||||
l.m_dir = static_cast<Directions> (m_dir - 1);
|
||||
l.m_dir = static_cast<Directions>( m_dir - 1 );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Function ToVector()
|
||||
*
|
||||
|
@ -295,19 +293,19 @@ public:
|
|||
*/
|
||||
const VECTOR2I ToVector() const
|
||||
{
|
||||
switch(m_dir)
|
||||
switch( m_dir )
|
||||
{
|
||||
case N: return VECTOR2I(0, 1);
|
||||
case S: return VECTOR2I(0, -1);
|
||||
case E: return VECTOR2I(1, 0);
|
||||
case W: return VECTOR2I(-1, 0);
|
||||
case NE: return VECTOR2I(1, 1);
|
||||
case NW: return VECTOR2I(-1, 1);
|
||||
case SE: return VECTOR2I(1, -1);
|
||||
case SW: return VECTOR2I(-1, -1);
|
||||
case N: return VECTOR2I( 0, 1 );
|
||||
case S: return VECTOR2I( 0, -1 );
|
||||
case E: return VECTOR2I( 1, 0 );
|
||||
case W: return VECTOR2I( -1, 0 );
|
||||
case NE: return VECTOR2I( 1, 1 );
|
||||
case NW: return VECTOR2I( -1, 1 );
|
||||
case SE: return VECTOR2I( 1, -1 );
|
||||
case SW: return VECTOR2I( -1, -1 );
|
||||
|
||||
default:
|
||||
return VECTOR2I(0, 0);
|
||||
return VECTOR2I( 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,17 +33,18 @@ class PNS_LOGGER;
|
|||
* Holds a bunch of objects commonly used by all algorithms (P&S settings, parent router instance, logging)
|
||||
**/
|
||||
|
||||
class PNS_ALGO_BASE {
|
||||
|
||||
class PNS_ALGO_BASE
|
||||
{
|
||||
public:
|
||||
PNS_ALGO_BASE ( PNS_ROUTER *aRouter ):
|
||||
PNS_ALGO_BASE( PNS_ROUTER *aRouter ) :
|
||||
m_router ( aRouter )
|
||||
{};
|
||||
{}
|
||||
|
||||
virtual ~PNS_ALGO_BASE() {}
|
||||
|
||||
///> Returns the instance of our router
|
||||
PNS_ROUTER *Router() const {
|
||||
PNS_ROUTER* Router() const
|
||||
{
|
||||
return m_router;
|
||||
}
|
||||
|
||||
|
@ -51,10 +52,10 @@ public:
|
|||
PNS_ROUTING_SETTINGS& Settings() const;
|
||||
|
||||
///> Returns the logger object, allowing to dump geometry to a file.
|
||||
virtual PNS_LOGGER *Logger();
|
||||
virtual PNS_LOGGER* Logger();
|
||||
|
||||
private:
|
||||
PNS_ROUTER *m_router;
|
||||
PNS_ROUTER* m_router;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,8 @@ PNS_DRAGGER::PNS_DRAGGER( PNS_ROUTER* aRouter ) :
|
|||
{
|
||||
m_world = NULL;
|
||||
m_shove = NULL;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
PNS_DRAGGER::~PNS_DRAGGER()
|
||||
{
|
||||
|
@ -37,97 +38,103 @@ PNS_DRAGGER::~PNS_DRAGGER()
|
|||
delete m_shove;
|
||||
}
|
||||
|
||||
void PNS_DRAGGER::SetWorld ( PNS_NODE *aWorld )
|
||||
|
||||
void PNS_DRAGGER::SetWorld ( PNS_NODE* aWorld )
|
||||
{
|
||||
m_world = aWorld;
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg )
|
||||
|
||||
bool PNS_DRAGGER::startDragSegment( const VECTOR2D& aP, PNS_SEGMENT* aSeg )
|
||||
{
|
||||
int w2 = aSeg->Width() / 2;
|
||||
|
||||
m_draggedLine = m_world->AssembleLine ( aSeg, &m_draggedSegmentIndex );
|
||||
m_shove->SetInitialLine (m_draggedLine);
|
||||
m_shove->SetInitialLine( m_draggedLine );
|
||||
m_lastValidDraggedLine = *m_draggedLine;
|
||||
m_lastValidDraggedLine.ClearSegmentLinks();
|
||||
|
||||
if( (aP - aSeg->Seg().A).EuclideanNorm() <= w2 )
|
||||
if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 )
|
||||
m_mode = CORNER;
|
||||
else if( (aP - aSeg->Seg().B).EuclideanNorm() <= w2 )
|
||||
else if( ( aP - aSeg->Seg().B ).EuclideanNorm() <= w2 )
|
||||
{
|
||||
m_draggedSegmentIndex ++;
|
||||
m_mode = CORNER;
|
||||
} else
|
||||
m_mode = SEGMENT;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA *aVia )
|
||||
|
||||
bool PNS_DRAGGER::startDragVia( const VECTOR2D& aP, PNS_VIA* aVia )
|
||||
{
|
||||
m_draggedVia = aVia;
|
||||
m_initialVia = aVia;
|
||||
m_mode = VIA;
|
||||
|
||||
VECTOR2I p0 ( aVia->Pos() );
|
||||
VECTOR2I p0( aVia->Pos() );
|
||||
PNS_JOINT *jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
|
||||
|
||||
BOOST_FOREACH(PNS_ITEM *item, jt->LinkList() )
|
||||
{
|
||||
if(item->OfKind( PNS_ITEM::SEGMENT ))
|
||||
if( item->OfKind( PNS_ITEM::SEGMENT ) )
|
||||
{
|
||||
int segIndex;
|
||||
PNS_SEGMENT *seg = (PNS_SEGMENT *) item;
|
||||
std::auto_ptr<PNS_LINE> l ( m_world->AssembleLine(seg, &segIndex) );
|
||||
|
||||
if(segIndex != 0)
|
||||
PNS_SEGMENT* seg = (PNS_SEGMENT*) item;
|
||||
std::auto_ptr<PNS_LINE> l( m_world->AssembleLine( seg, &segIndex ) );
|
||||
|
||||
if( segIndex != 0 )
|
||||
l->Reverse();
|
||||
|
||||
m_origViaConnections.push_back (*l);
|
||||
|
||||
m_origViaConnections.push_back( *l );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
||||
|
||||
bool PNS_DRAGGER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
||||
{
|
||||
m_shove = new PNS_SHOVE ( m_world, Router() );
|
||||
m_shove = new PNS_SHOVE( m_world, Router() );
|
||||
m_lastNode = NULL;
|
||||
m_draggedItems.Clear();
|
||||
m_currentMode = Settings().Mode();
|
||||
|
||||
TRACE(2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind());
|
||||
TRACE( 2, "StartDragging: item %p [kind %d]", aStartItem % aStartItem->Kind() );
|
||||
|
||||
switch( aStartItem->Kind() )
|
||||
{
|
||||
case PNS_ITEM::SEGMENT:
|
||||
return startDragSegment ( aP, static_cast<PNS_SEGMENT *> (aStartItem) );
|
||||
return startDragSegment ( aP, static_cast<PNS_SEGMENT *>( aStartItem ) );
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
return startDragVia ( aP, static_cast<PNS_VIA *> (aStartItem) );
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP)
|
||||
|
||||
bool PNS_DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
|
||||
{
|
||||
if(m_lastNode)
|
||||
if( m_lastNode )
|
||||
{
|
||||
delete m_lastNode;
|
||||
m_lastNode = NULL;
|
||||
}
|
||||
|
||||
switch(m_mode)
|
||||
switch( m_mode )
|
||||
{
|
||||
case SEGMENT:
|
||||
case CORNER:
|
||||
{
|
||||
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
|
||||
PNS_LINE tmp (*m_draggedLine);
|
||||
PNS_LINE tmp( *m_draggedLine );
|
||||
|
||||
if(m_mode == SEGMENT)
|
||||
if( m_mode == SEGMENT )
|
||||
tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh );
|
||||
else
|
||||
tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh );
|
||||
|
@ -143,17 +150,17 @@ bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case VIA: // fixme...
|
||||
{
|
||||
m_lastNode = m_shove->CurrentNode()->Branch();
|
||||
dumbDragVia ( m_initialVia, m_lastNode, aP );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Settings().CanViolateDRC())
|
||||
if( Settings().CanViolateDRC() )
|
||||
m_dragStatus = true;
|
||||
else
|
||||
m_dragStatus = !m_world->CheckColliding( m_draggedItems );
|
||||
|
@ -161,60 +168,62 @@ bool PNS_DRAGGER::dragMarkObstacles(const VECTOR2I& aP)
|
|||
return true;
|
||||
}
|
||||
|
||||
void PNS_DRAGGER::dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP )
|
||||
|
||||
void PNS_DRAGGER::dumbDragVia( PNS_VIA* aVia, PNS_NODE* aNode, const VECTOR2I& aP )
|
||||
{
|
||||
// fixme: this is awful.
|
||||
m_draggedVia = aVia->Clone();
|
||||
m_draggedVia->SetPos( aP );
|
||||
m_draggedItems.Clear();
|
||||
m_draggedItems.Add(m_draggedVia);
|
||||
m_draggedItems.Add( m_draggedVia );
|
||||
|
||||
m_lastNode->Remove ( aVia );
|
||||
m_lastNode->Add ( m_draggedVia );
|
||||
m_lastNode->Remove( aVia );
|
||||
m_lastNode->Add( m_draggedVia );
|
||||
|
||||
BOOST_FOREACH(PNS_LINE &l, m_origViaConnections)
|
||||
BOOST_FOREACH( PNS_LINE &l, m_origViaConnections )
|
||||
{
|
||||
PNS_LINE origLine (l);
|
||||
PNS_LINE *draggedLine = l.Clone();
|
||||
PNS_LINE* draggedLine = l.Clone();
|
||||
|
||||
draggedLine->DragCorner( aP, 0 );
|
||||
draggedLine->ClearSegmentLinks();
|
||||
|
||||
m_draggedItems.AddOwned( draggedLine );
|
||||
|
||||
m_lastNode->Remove ( &origLine );
|
||||
m_lastNode->Add ( draggedLine );
|
||||
m_lastNode->Remove( &origLine );
|
||||
m_lastNode->Add( draggedLine );
|
||||
}
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::dragShove(const VECTOR2I& aP)
|
||||
|
||||
bool PNS_DRAGGER::dragShove( const VECTOR2I& aP )
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
|
||||
if(m_lastNode)
|
||||
if( m_lastNode )
|
||||
{
|
||||
delete m_lastNode;
|
||||
m_lastNode = NULL;
|
||||
}
|
||||
|
||||
switch(m_mode)
|
||||
switch( m_mode )
|
||||
{
|
||||
case SEGMENT:
|
||||
case CORNER:
|
||||
{
|
||||
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine->Width() / 4 : 0;
|
||||
PNS_LINE tmp (*m_draggedLine);
|
||||
if(m_mode == SEGMENT)
|
||||
tmp.DragSegment ( aP, m_draggedSegmentIndex, thresh );
|
||||
PNS_LINE tmp( *m_draggedLine );
|
||||
|
||||
if( m_mode == SEGMENT )
|
||||
tmp.DragSegment( aP, m_draggedSegmentIndex, thresh );
|
||||
else
|
||||
tmp.DragCorner ( aP, m_draggedSegmentIndex, thresh );
|
||||
tmp.DragCorner( aP, m_draggedSegmentIndex, thresh );
|
||||
|
||||
PNS_SHOVE::ShoveStatus st = m_shove->ShoveLines( tmp );
|
||||
PNS_SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( tmp );
|
||||
|
||||
if(st == PNS_SHOVE::SH_OK)
|
||||
if( st == PNS_SHOVE::SH_OK )
|
||||
ok = true;
|
||||
else if (st == PNS_SHOVE::SH_HEAD_MODIFIED)
|
||||
else if( st == PNS_SHOVE::SH_HEAD_MODIFIED )
|
||||
{
|
||||
tmp = m_shove->NewHead();
|
||||
ok = true;
|
||||
|
@ -222,22 +231,23 @@ bool PNS_DRAGGER::dragShove(const VECTOR2I& aP)
|
|||
|
||||
m_lastNode = m_shove->CurrentNode()->Branch();
|
||||
|
||||
if(ok)
|
||||
if( ok )
|
||||
m_lastValidDraggedLine = tmp;
|
||||
|
||||
m_lastValidDraggedLine.ClearSegmentLinks();
|
||||
m_lastValidDraggedLine.Unmark();
|
||||
m_lastNode->Add ( &m_lastValidDraggedLine );
|
||||
m_draggedItems = PNS_ITEMSET ( &m_lastValidDraggedLine );
|
||||
m_lastNode->Add( &m_lastValidDraggedLine );
|
||||
m_draggedItems = PNS_ITEMSET( &m_lastValidDraggedLine );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case VIA:
|
||||
{
|
||||
PNS_VIA *newVia;
|
||||
PNS_SHOVE::ShoveStatus st = m_shove -> ShoveDraggingVia ( m_draggedVia, aP, &newVia );
|
||||
PNS_SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, &newVia );
|
||||
|
||||
if(st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED)
|
||||
if( st == PNS_SHOVE::SH_OK || st == PNS_SHOVE::SH_HEAD_MODIFIED )
|
||||
ok = true;
|
||||
|
||||
m_lastNode = m_shove->CurrentNode()->Branch();
|
||||
|
@ -250,16 +260,17 @@ bool PNS_DRAGGER::dragShove(const VECTOR2I& aP)
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_dragStatus = ok;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::FixRoute( )
|
||||
|
||||
bool PNS_DRAGGER::FixRoute()
|
||||
{
|
||||
if(m_dragStatus)
|
||||
if( m_dragStatus )
|
||||
{
|
||||
Router()->CommitRouting( CurrentNode() );
|
||||
return true;
|
||||
|
@ -267,35 +278,42 @@ bool PNS_DRAGGER::FixRoute( )
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PNS_DRAGGER::Drag ( const VECTOR2I& aP )
|
||||
|
||||
|
||||
bool PNS_DRAGGER::Drag( const VECTOR2I& aP )
|
||||
{
|
||||
switch ( m_currentMode )
|
||||
switch( m_currentMode )
|
||||
{
|
||||
case RM_MarkObstacles:
|
||||
return dragMarkObstacles (aP);
|
||||
return dragMarkObstacles( aP );
|
||||
|
||||
case RM_Shove:
|
||||
case RM_Walkaround:
|
||||
case RM_Smart:
|
||||
return dragShove ( aP );
|
||||
return dragShove( aP );
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE *PNS_DRAGGER::CurrentNode() const
|
||||
{
|
||||
return m_lastNode;
|
||||
}
|
||||
|
||||
|
||||
const PNS_ITEMSET PNS_DRAGGER::Traces()
|
||||
{
|
||||
return m_draggedItems;
|
||||
}
|
||||
|
||||
PNS_LOGGER *PNS_DRAGGER::Logger()
|
||||
|
||||
PNS_LOGGER* PNS_DRAGGER::Logger()
|
||||
{
|
||||
if(m_shove)
|
||||
if( m_shove )
|
||||
return m_shove->Logger();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -39,12 +39,10 @@ class PNS_ROUTER_BASE;
|
|||
*
|
||||
* Via, segment and corner dragging algorithm.
|
||||
*/
|
||||
|
||||
class PNS_DRAGGER : public PNS_ALGO_BASE
|
||||
{
|
||||
public:
|
||||
|
||||
PNS_DRAGGER( PNS_ROUTER *aRouter );
|
||||
PNS_DRAGGER( PNS_ROUTER* aRouter );
|
||||
~PNS_DRAGGER();
|
||||
|
||||
/**
|
||||
|
@ -52,8 +50,7 @@ public:
|
|||
*
|
||||
* Sets the board to work on.
|
||||
*/
|
||||
void SetWorld ( PNS_NODE *aWorld );
|
||||
|
||||
void SetWorld( PNS_NODE* aWorld );
|
||||
|
||||
/**
|
||||
* Function Start()
|
||||
|
@ -61,7 +58,7 @@ public:
|
|||
* Starts routing a single track at point aP, taking item aStartItem as anchor
|
||||
* (unless NULL). Returns true if a dragging operation has started.
|
||||
*/
|
||||
bool Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem );
|
||||
bool Start( const VECTOR2I& aP, PNS_ITEM* aStartItem );
|
||||
|
||||
/**
|
||||
* Function Drag()
|
||||
|
@ -69,7 +66,7 @@ public:
|
|||
* Drags the current segment/corner/via to the point aP.
|
||||
* @return true, if dragging finished with success.
|
||||
*/
|
||||
bool Drag ( const VECTOR2I& aP );
|
||||
bool Drag( const VECTOR2I& aP );
|
||||
|
||||
/**
|
||||
* Function FixRoute()
|
||||
|
@ -78,7 +75,7 @@ public:
|
|||
* and eventually commits it to the world.
|
||||
* @return true, if dragging finished with success.
|
||||
*/
|
||||
bool FixRoute ( );
|
||||
bool FixRoute();
|
||||
|
||||
/**
|
||||
* Function CurrentNode()
|
||||
|
@ -86,7 +83,6 @@ public:
|
|||
* Returns the most recent world state, including all
|
||||
* items changed due to dragging operation.
|
||||
*/
|
||||
|
||||
PNS_NODE* CurrentNode() const;
|
||||
|
||||
/**
|
||||
|
@ -97,11 +93,10 @@ public:
|
|||
const PNS_ITEMSET Traces();
|
||||
|
||||
/// @copydoc PNS_ALGO_BASE::Logger()
|
||||
virtual PNS_LOGGER *Logger();
|
||||
virtual PNS_LOGGER* Logger();
|
||||
|
||||
private:
|
||||
|
||||
typedef std::pair <PNS_LINE *, PNS_LINE *> LinePair;
|
||||
typedef std::pair<PNS_LINE *, PNS_LINE *> LinePair;
|
||||
typedef std::vector<LinePair> LinePairVec;
|
||||
|
||||
enum DragMode {
|
||||
|
@ -110,26 +105,26 @@ private:
|
|||
VIA
|
||||
};
|
||||
|
||||
bool dragMarkObstacles(const VECTOR2I& aP);
|
||||
bool dragShove(const VECTOR2I& aP);
|
||||
bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT *aSeg );
|
||||
bool startDragVia( const VECTOR2D& aP, PNS_VIA *aVia );
|
||||
void dumbDragVia ( PNS_VIA *aVia, PNS_NODE *aNode, const VECTOR2I& aP );
|
||||
bool dragMarkObstacles( const VECTOR2I& aP );
|
||||
bool dragShove(const VECTOR2I& aP );
|
||||
bool startDragSegment( const VECTOR2D& aP, PNS_SEGMENT* aSeg );
|
||||
bool startDragVia( const VECTOR2D& aP, PNS_VIA* aVia );
|
||||
void dumbDragVia( PNS_VIA* aVia, PNS_NODE* aNode, const VECTOR2I& aP );
|
||||
|
||||
PNS_NODE * m_world;
|
||||
PNS_NODE * m_lastNode;
|
||||
DragMode m_mode;
|
||||
PNS_LINE * m_draggedLine;
|
||||
PNS_VIA * m_draggedVia;
|
||||
PNS_LINE m_lastValidDraggedLine;
|
||||
PNS_SHOVE * m_shove;
|
||||
int m_draggedSegmentIndex;
|
||||
bool m_dragStatus;
|
||||
PNS_NODE* m_world;
|
||||
PNS_NODE* m_lastNode;
|
||||
DragMode m_mode;
|
||||
PNS_LINE* m_draggedLine;
|
||||
PNS_VIA* m_draggedVia;
|
||||
PNS_LINE m_lastValidDraggedLine;
|
||||
PNS_SHOVE* m_shove;
|
||||
int m_draggedSegmentIndex;
|
||||
bool m_dragStatus;
|
||||
PNS_MODE m_currentMode;
|
||||
std::vector<PNS_LINE> m_origViaConnections;
|
||||
std::vector<PNS_LINE> m_draggedViaConnections;
|
||||
PNS_VIA * m_initialVia;
|
||||
PNS_ITEMSET m_draggedItems;
|
||||
std::vector<PNS_LINE> m_origViaConnections;
|
||||
std::vector<PNS_LINE> m_draggedViaConnections;
|
||||
PNS_VIA* m_initialVia;
|
||||
PNS_ITEMSET m_draggedItems;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -39,13 +39,12 @@
|
|||
* are assigned to separate R-Tree subindices depending on their type and spanned layers, reducing
|
||||
* overlap and improving search time.
|
||||
**/
|
||||
|
||||
class PNS_INDEX
|
||||
{
|
||||
public:
|
||||
typedef std::list<PNS_ITEM*> NetItemsList;
|
||||
typedef SHAPE_INDEX<PNS_ITEM*> ItemShapeIndex;
|
||||
typedef boost::unordered_set<PNS_ITEM*> ItemSet;
|
||||
typedef std::list<PNS_ITEM*> NET_ITEMS_LIST;
|
||||
typedef SHAPE_INDEX<PNS_ITEM*> ITEM_SHAPE_INDEX;
|
||||
typedef boost::unordered_set<PNS_ITEM*> ITEM_SET;
|
||||
|
||||
PNS_INDEX();
|
||||
~PNS_INDEX();
|
||||
|
@ -115,7 +114,7 @@ public:
|
|||
*
|
||||
* Returns list of all items in a given net.
|
||||
*/
|
||||
NetItemsList* GetItemsForNet( int aNet );
|
||||
NET_ITEMS_LIST* GetItemsForNet( int aNet );
|
||||
|
||||
/**
|
||||
* Function Contains()
|
||||
|
@ -134,36 +133,35 @@ public:
|
|||
*/
|
||||
int Size() const { return m_allItems.size(); }
|
||||
|
||||
ItemSet::iterator begin() { return m_allItems.begin(); }
|
||||
ItemSet::iterator end() { return m_allItems.end(); }
|
||||
ITEM_SET::iterator begin() { return m_allItems.begin(); }
|
||||
ITEM_SET::iterator end() { return m_allItems.end(); }
|
||||
|
||||
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 SI_Traces = 3;
|
||||
static const int SI_PadsTop = 0;
|
||||
static const int SI_PadsBottom = 1;
|
||||
|
||||
template <class Visitor>
|
||||
int querySingle( int index, const SHAPE* aShape, int aMinDistance, Visitor& aVisitor );
|
||||
|
||||
ItemShapeIndex* getSubindex( const PNS_ITEM* aItem );
|
||||
ITEM_SHAPE_INDEX* getSubindex( const PNS_ITEM* aItem );
|
||||
|
||||
ItemShapeIndex* m_subIndices[MaxSubIndices];
|
||||
std::map<int, NetItemsList> m_netMap;
|
||||
ItemSet m_allItems;
|
||||
ITEM_SHAPE_INDEX* m_subIndices[MaxSubIndices];
|
||||
std::map<int, NET_ITEMS_LIST> m_netMap;
|
||||
ITEM_SET m_allItems;
|
||||
};
|
||||
|
||||
|
||||
PNS_INDEX::PNS_INDEX()
|
||||
{
|
||||
memset( m_subIndices, 0, sizeof( m_subIndices ) );
|
||||
}
|
||||
|
||||
|
||||
PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
|
||||
PNS_INDEX::ITEM_SHAPE_INDEX* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
|
||||
{
|
||||
int idx_n = -1;
|
||||
|
||||
|
@ -199,7 +197,7 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
|
|||
assert( idx_n >= 0 && idx_n < MaxSubIndices );
|
||||
|
||||
if( !m_subIndices[idx_n] )
|
||||
m_subIndices[idx_n] = new ItemShapeIndex;
|
||||
m_subIndices[idx_n] = new ITEM_SHAPE_INDEX;
|
||||
|
||||
return m_subIndices[idx_n];
|
||||
}
|
||||
|
@ -207,10 +205,8 @@ PNS_INDEX::ItemShapeIndex* PNS_INDEX::getSubindex( const PNS_ITEM* aItem )
|
|||
|
||||
void PNS_INDEX::Add( PNS_ITEM* aItem )
|
||||
{
|
||||
ItemShapeIndex* idx = getSubindex( aItem );
|
||||
ITEM_SHAPE_INDEX* idx = getSubindex( aItem );
|
||||
|
||||
|
||||
|
||||
idx->Add( aItem );
|
||||
m_allItems.insert( aItem );
|
||||
int net = aItem->Net();
|
||||
|
@ -224,7 +220,7 @@ void PNS_INDEX::Add( PNS_ITEM* aItem )
|
|||
|
||||
void PNS_INDEX::Remove( PNS_ITEM* aItem )
|
||||
{
|
||||
ItemShapeIndex* idx = getSubindex( aItem );
|
||||
ITEM_SHAPE_INDEX* idx = getSubindex( aItem );
|
||||
|
||||
idx->Remove( aItem );
|
||||
m_allItems.erase( aItem );
|
||||
|
@ -303,7 +299,7 @@ void PNS_INDEX::Clear()
|
|||
{
|
||||
for( int i = 0; i < MaxSubIndices; ++i )
|
||||
{
|
||||
ItemShapeIndex* idx = m_subIndices[i];
|
||||
ITEM_SHAPE_INDEX* idx = m_subIndices[i];
|
||||
|
||||
if( idx )
|
||||
delete idx;
|
||||
|
@ -319,7 +315,7 @@ PNS_INDEX::~PNS_INDEX()
|
|||
}
|
||||
|
||||
|
||||
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet( int aNet )
|
||||
PNS_INDEX::NET_ITEMS_LIST* PNS_INDEX::GetItemsForNet( int aNet )
|
||||
{
|
||||
if( m_netMap.find( aNet ) == m_netMap.end() )
|
||||
return NULL;
|
||||
|
|
|
@ -50,8 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
|||
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
|
||||
|
||||
if( line->EndsWithVia() )
|
||||
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV,
|
||||
aMTV );
|
||||
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV );
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -85,5 +84,4 @@ const std::string PNS_ITEM::KindStr() const
|
|||
|
||||
PNS_ITEM::~PNS_ITEM()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public:
|
|||
*
|
||||
* Returns a deep copy of the item
|
||||
*/
|
||||
virtual PNS_ITEM* Clone( ) const = 0;
|
||||
virtual PNS_ITEM* Clone() const = 0;
|
||||
|
||||
/*
|
||||
* Function Hull()
|
||||
|
@ -104,7 +104,7 @@ public:
|
|||
virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const
|
||||
{
|
||||
return SHAPE_LINE_CHAIN();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function Kind()
|
||||
|
@ -123,7 +123,7 @@ public:
|
|||
*/
|
||||
bool OfKind( int aKindMask ) const
|
||||
{
|
||||
return (aKindMask & m_kind) != 0;
|
||||
return ( aKindMask & m_kind ) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -219,7 +219,7 @@ public:
|
|||
* Returns true if the set of layers spanned by aOther overlaps our
|
||||
* layers.
|
||||
*/
|
||||
bool LayersOverlap( const PNS_ITEM *aOther ) const
|
||||
bool LayersOverlap( const PNS_ITEM* aOther ) const
|
||||
{
|
||||
return Layers().Overlaps( aOther->Layers() );
|
||||
}
|
||||
|
@ -252,7 +252,6 @@ public:
|
|||
*/
|
||||
PNS_NODE* Owner() const { return m_owner; }
|
||||
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
|
@ -308,7 +307,7 @@ public:
|
|||
return m_marker;
|
||||
}
|
||||
|
||||
virtual void SetRank ( int aRank )
|
||||
virtual void SetRank( int aRank )
|
||||
{
|
||||
m_rank = aRank;
|
||||
}
|
||||
|
@ -318,10 +317,10 @@ public:
|
|||
return m_rank;
|
||||
}
|
||||
|
||||
virtual VECTOR2I Anchor(int n) const
|
||||
virtual VECTOR2I Anchor( int n ) const
|
||||
{
|
||||
return VECTOR2I ();
|
||||
};
|
||||
}
|
||||
|
||||
virtual int AnchorCount() const
|
||||
{
|
||||
|
@ -329,15 +328,14 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||
VECTOR2I& aMTV ) const;
|
||||
|
||||
protected:
|
||||
PnsKind m_kind;
|
||||
|
||||
BOARD_CONNECTED_ITEM *m_parent;
|
||||
PNS_NODE *m_owner;
|
||||
BOARD_CONNECTED_ITEM* m_parent;
|
||||
PNS_NODE* m_owner;
|
||||
PNS_LAYERSET m_layers;
|
||||
|
||||
bool m_movable;
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
|
||||
#include "pns_itemset.h"
|
||||
|
||||
|
||||
PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM *aInitialItem )
|
||||
PNS_ITEMSET::PNS_ITEMSET( PNS_ITEM* aInitialItem )
|
||||
{
|
||||
if(aInitialItem)
|
||||
m_items.push_back(aInitialItem);
|
||||
|
@ -38,7 +37,7 @@ PNS_ITEMSET::~PNS_ITEMSET()
|
|||
|
||||
void PNS_ITEMSET::Clear()
|
||||
{
|
||||
BOOST_FOREACH(PNS_ITEM *item, m_ownedItems)
|
||||
BOOST_FOREACH(PNS_ITEM* item, m_ownedItems)
|
||||
{
|
||||
delete item;
|
||||
}
|
||||
|
@ -47,9 +46,10 @@ void PNS_ITEMSET::Clear()
|
|||
m_ownedItems.clear();
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
|
||||
{
|
||||
ItemVector newItems;
|
||||
ITEM_VECTOR newItems;
|
||||
PNS_LAYERSET l;
|
||||
|
||||
if( aEnd < 0 )
|
||||
|
@ -57,39 +57,44 @@ PNS_ITEMSET& PNS_ITEMSET::FilterLayers( int aStart, int aEnd )
|
|||
else
|
||||
l = PNS_LAYERSET( aStart, aEnd );
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
BOOST_FOREACH( PNS_ITEM* item, m_items )
|
||||
|
||||
if( item->Layers().Overlaps( l ) )
|
||||
newItems.push_back( item );
|
||||
|
||||
m_items = newItems;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterKinds( int aKindMask )
|
||||
{
|
||||
ItemVector newItems;
|
||||
ITEM_VECTOR newItems;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
|
||||
if( item->OfKind ( aKindMask ) )
|
||||
newItems.push_back( item );
|
||||
BOOST_FOREACH( PNS_ITEM* item, m_items )
|
||||
{
|
||||
if( item->OfKind ( aKindMask ) )
|
||||
newItems.push_back( item );
|
||||
}
|
||||
|
||||
m_items = newItems;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEMSET& PNS_ITEMSET::FilterNet( int aNet )
|
||||
{
|
||||
ItemVector newItems;
|
||||
ITEM_VECTOR newItems;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_items )
|
||||
|
||||
if( item->Net() == aNet )
|
||||
newItems.push_back( item );
|
||||
BOOST_FOREACH( PNS_ITEM* item, m_items )
|
||||
{
|
||||
if( item->Net() == aNet )
|
||||
newItems.push_back( item );
|
||||
}
|
||||
|
||||
m_items = newItems;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -35,27 +35,28 @@
|
|||
class PNS_ITEMSET
|
||||
{
|
||||
public:
|
||||
typedef std::vector<PNS_ITEM*> ItemVector;
|
||||
typedef std::vector<PNS_ITEM*> ITEM_VECTOR;
|
||||
|
||||
PNS_ITEMSET( PNS_ITEM *aInitialItem = NULL );
|
||||
PNS_ITEMSET( PNS_ITEM* aInitialItem = NULL );
|
||||
|
||||
PNS_ITEMSET (const PNS_ITEMSET &aOther )
|
||||
PNS_ITEMSET( const PNS_ITEMSET& aOther )
|
||||
{
|
||||
m_items = aOther.m_items;
|
||||
m_ownedItems = ItemVector();
|
||||
m_ownedItems = ITEM_VECTOR();
|
||||
}
|
||||
|
||||
const PNS_ITEMSET& operator= (const PNS_ITEMSET &aOther)
|
||||
const PNS_ITEMSET& operator=( const PNS_ITEMSET& aOther )
|
||||
{
|
||||
m_items = aOther.m_items;
|
||||
m_ownedItems = ItemVector();
|
||||
m_ownedItems = ITEM_VECTOR();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~PNS_ITEMSET();
|
||||
|
||||
ItemVector& Items() { return m_items; }
|
||||
const ItemVector& CItems() const { return m_items; }
|
||||
ITEM_VECTOR& Items() { return m_items; }
|
||||
const ITEM_VECTOR& CItems() const { return m_items; }
|
||||
|
||||
PNS_ITEMSET& FilterLayers( int aStart, int aEnd = -1 );
|
||||
PNS_ITEMSET& FilterKinds( int aKindMask );
|
||||
|
@ -63,24 +64,24 @@ public:
|
|||
|
||||
int Size() { return m_items.size(); }
|
||||
|
||||
void Add( PNS_ITEM* item )
|
||||
void Add( PNS_ITEM* aItem )
|
||||
{
|
||||
m_items.push_back( item );
|
||||
m_items.push_back( aItem );
|
||||
}
|
||||
|
||||
PNS_ITEM* Get( int index ) const { return m_items[index]; }
|
||||
|
||||
void Clear();
|
||||
|
||||
void AddOwned ( PNS_ITEM *aItem )
|
||||
void AddOwned( PNS_ITEM *aItem )
|
||||
{
|
||||
m_items.push_back( aItem );
|
||||
m_ownedItems.push_back( aItem );
|
||||
}
|
||||
|
||||
private:
|
||||
ItemVector m_items;
|
||||
ItemVector m_ownedItems;
|
||||
ITEM_VECTOR m_items;
|
||||
ITEM_VECTOR m_ownedItems;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -40,11 +40,11 @@
|
|||
class PNS_JOINT : public PNS_ITEM
|
||||
{
|
||||
public:
|
||||
typedef std::vector<PNS_ITEM*> LinkedItems;
|
||||
typedef std::vector<PNS_ITEM*> LINKED_ITEMS;
|
||||
|
||||
///> Joints are hashed by their position, layers and net.
|
||||
/// Linked items are, obviously, not hashed
|
||||
struct HashTag
|
||||
struct HASH_TAG
|
||||
{
|
||||
VECTOR2I pos;
|
||||
int net;
|
||||
|
@ -53,8 +53,7 @@ public:
|
|||
PNS_JOINT() :
|
||||
PNS_ITEM( JOINT ) {}
|
||||
|
||||
PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
|
||||
int aNet = -1 ) :
|
||||
PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1 ) :
|
||||
PNS_ITEM( JOINT )
|
||||
{
|
||||
m_tag.pos = aPos;
|
||||
|
@ -62,14 +61,14 @@ public:
|
|||
m_layers = aLayers;
|
||||
}
|
||||
|
||||
PNS_JOINT( const PNS_JOINT& b ) :
|
||||
PNS_JOINT( const PNS_JOINT& aB ) :
|
||||
PNS_ITEM( JOINT )
|
||||
{
|
||||
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;
|
||||
m_layers = aB.m_layers;
|
||||
m_tag.pos = aB.m_tag.pos;
|
||||
m_tag.net = aB.m_tag.net;
|
||||
m_linkedItems = aB.m_linkedItems;
|
||||
m_layers = aB.m_layers;
|
||||
}
|
||||
|
||||
PNS_ITEM* Clone ( ) const
|
||||
|
@ -85,8 +84,7 @@ public:
|
|||
if( m_linkedItems.size() != 2 )
|
||||
return false;
|
||||
|
||||
if( m_linkedItems[0]->Kind() != SEGMENT ||
|
||||
m_linkedItems[1]->Kind() != SEGMENT )
|
||||
if( m_linkedItems[0]->Kind() != SEGMENT || m_linkedItems[1]->Kind() != SEGMENT )
|
||||
return false;
|
||||
|
||||
PNS_SEGMENT* seg1 = static_cast<PNS_SEGMENT*>( m_linkedItems[0] );
|
||||
|
@ -99,8 +97,7 @@ public:
|
|||
///> Links the joint to a given board item (when it's added to the PNS_NODE)
|
||||
void Link( PNS_ITEM* aItem )
|
||||
{
|
||||
LinkedItems::iterator f = std::find( m_linkedItems.begin(),
|
||||
m_linkedItems.end(), aItem );
|
||||
LINKED_ITEMS::iterator f = std::find( m_linkedItems.begin(), m_linkedItems.end(), aItem );
|
||||
|
||||
if( f != m_linkedItems.end() )
|
||||
return;
|
||||
|
@ -112,8 +109,7 @@ public:
|
|||
///> Returns true if the joint became dangling after unlinking.
|
||||
bool Unlink( PNS_ITEM* aItem )
|
||||
{
|
||||
LinkedItems::iterator f = std::find( m_linkedItems.begin(),
|
||||
m_linkedItems.end(), aItem );
|
||||
LINKED_ITEMS::iterator f = std::find( m_linkedItems.begin(), m_linkedItems.end(), aItem );
|
||||
|
||||
if( f != m_linkedItems.end() )
|
||||
m_linkedItems.erase( f );
|
||||
|
@ -131,17 +127,19 @@ public:
|
|||
return static_cast<PNS_SEGMENT*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
|
||||
}
|
||||
|
||||
PNS_VIA *Via()
|
||||
PNS_VIA* Via()
|
||||
{
|
||||
for( LinkedItems::iterator i = m_linkedItems.begin();
|
||||
i != m_linkedItems.end(); ++i )
|
||||
for( LINKED_ITEMS::iterator i = m_linkedItems.begin(); i != m_linkedItems.end(); ++i )
|
||||
{
|
||||
if( (*i)->Kind() == PNS_ITEM::VIA )
|
||||
return (PNS_VIA *)(*i);
|
||||
return (PNS_VIA*)( *i );
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// trivial accessors
|
||||
const HashTag& Tag() const
|
||||
const HASH_TAG& Tag() const
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
|
@ -156,7 +154,7 @@ public:
|
|||
return m_tag.net;
|
||||
}
|
||||
|
||||
LinkedItems& LinkList()
|
||||
LINKED_ITEMS& LinkList()
|
||||
{
|
||||
return m_linkedItems;
|
||||
}
|
||||
|
@ -166,10 +164,12 @@ public:
|
|||
{
|
||||
int n = 0;
|
||||
|
||||
for( LinkedItems::const_iterator i = m_linkedItems.begin();
|
||||
i != m_linkedItems.end(); ++i )
|
||||
for( LINKED_ITEMS::const_iterator i = m_linkedItems.begin();
|
||||
i != m_linkedItems.end(); ++i )
|
||||
{
|
||||
if( (*i)->Kind() & aMask )
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -189,9 +189,11 @@ public:
|
|||
m_layers.Merge( aJoint.m_layers );
|
||||
|
||||
// fixme: duplicate links (?)
|
||||
for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin();
|
||||
i != aJoint.m_linkedItems.end(); ++i )
|
||||
for( LINKED_ITEMS::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
|
||||
|
@ -202,27 +204,27 @@ public:
|
|||
|
||||
private:
|
||||
///> hash tag for unordered_multimap
|
||||
HashTag m_tag;
|
||||
HASH_TAG m_tag;
|
||||
|
||||
///> list of items linked to this joint
|
||||
LinkedItems m_linkedItems;
|
||||
LINKED_ITEMS m_linkedItems;
|
||||
};
|
||||
|
||||
|
||||
// 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::HASH_TAG const& aP1,
|
||||
PNS_JOINT::HASH_TAG const& aP2 )
|
||||
{
|
||||
return p1.pos == p2.pos && p1.net == p2.net;
|
||||
return aP1.pos == aP2.pos && aP1.net == aP2.net;
|
||||
}
|
||||
|
||||
|
||||
inline std::size_t hash_value( PNS_JOINT::HashTag const& p )
|
||||
inline std::size_t hash_value( PNS_JOINT::HASH_TAG const& aP )
|
||||
{
|
||||
std::size_t seed = 0;
|
||||
boost::hash_combine( seed, p.pos.x );
|
||||
boost::hash_combine( seed, p.pos.y );
|
||||
boost::hash_combine( seed, p.net );
|
||||
boost::hash_combine( seed, aP.pos.x );
|
||||
boost::hash_combine( seed, aP.pos.y );
|
||||
boost::hash_combine( seed, aP.net );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
|
|
@ -50,17 +50,17 @@ public:
|
|||
m_start = m_end = aLayer;
|
||||
}
|
||||
|
||||
PNS_LAYERSET( const PNS_LAYERSET& b ) :
|
||||
m_start( b.m_start ),
|
||||
m_end( b.m_end )
|
||||
PNS_LAYERSET( const PNS_LAYERSET& aB ) :
|
||||
m_start( aB.m_start ),
|
||||
m_end( aB.m_end )
|
||||
{}
|
||||
|
||||
~PNS_LAYERSET() {};
|
||||
|
||||
const PNS_LAYERSET& operator=( const PNS_LAYERSET& b )
|
||||
const PNS_LAYERSET& operator=( const PNS_LAYERSET& aB )
|
||||
{
|
||||
m_start = b.m_start;
|
||||
m_end = b.m_end;
|
||||
m_start = aB.m_start;
|
||||
m_end = aB.m_end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,14 +50,15 @@ PNS_LINE::PNS_LINE( const PNS_LINE& aOther ) :
|
|||
copyLinks ( &aOther );
|
||||
}
|
||||
|
||||
|
||||
PNS_LINE::~PNS_LINE()
|
||||
{
|
||||
if( m_segmentRefs )
|
||||
delete m_segmentRefs;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const PNS_LINE& PNS_LINE :: operator= (const PNS_LINE& aOther)
|
||||
const PNS_LINE& PNS_LINE::operator=( const PNS_LINE& aOther )
|
||||
{
|
||||
m_line = aOther.m_line;
|
||||
m_width = aOther.m_width;
|
||||
|
@ -75,53 +76,62 @@ const PNS_LINE& PNS_LINE :: operator= (const PNS_LINE& aOther)
|
|||
return *this;
|
||||
}
|
||||
|
||||
PNS_LINE* PNS_LINE::Clone( ) const
|
||||
|
||||
PNS_LINE* PNS_LINE::Clone() const
|
||||
{
|
||||
PNS_LINE* l = new PNS_LINE( *this );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void PNS_LINE::Mark(int aMarker)
|
||||
|
||||
void PNS_LINE::Mark( int aMarker )
|
||||
{
|
||||
m_marker = aMarker;
|
||||
|
||||
if(m_segmentRefs)
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs )
|
||||
s->Mark(aMarker);
|
||||
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
|
||||
s->Mark( aMarker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::Unmark ()
|
||||
{
|
||||
if(m_segmentRefs)
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs )
|
||||
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
|
||||
s->Unmark();
|
||||
}
|
||||
|
||||
m_marker = 0;
|
||||
}
|
||||
|
||||
|
||||
int PNS_LINE::Marker()const
|
||||
{
|
||||
int marker = m_marker;
|
||||
if(m_segmentRefs)
|
||||
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs )
|
||||
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
|
||||
marker |= s->Marker();
|
||||
}
|
||||
|
||||
return marker;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::copyLinks( const PNS_LINE *aParent )
|
||||
{
|
||||
if(aParent->m_segmentRefs == NULL)
|
||||
if( aParent->m_segmentRefs == NULL )
|
||||
{
|
||||
m_segmentRefs = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
m_segmentRefs = new SegmentRefs();
|
||||
m_segmentRefs = new SEGMENT_REFS();
|
||||
*m_segmentRefs = *aParent->m_segmentRefs;
|
||||
}
|
||||
|
||||
|
@ -140,6 +150,7 @@ PNS_SEGMENT* PNS_SEGMENT::Clone( ) const
|
|||
return s;
|
||||
}
|
||||
|
||||
|
||||
int PNS_LINE::CountCorners( int aAngles )
|
||||
{
|
||||
int count = 0;
|
||||
|
@ -161,6 +172,7 @@ int PNS_LINE::CountCorners( int aAngles )
|
|||
return count;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
|
||||
SHAPE_LINE_CHAIN& aWalk, SHAPE_LINE_CHAIN& aPost, bool aCw ) const
|
||||
{
|
||||
|
@ -171,38 +183,37 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
|
|||
if( line.SegmentCount() < 1 )
|
||||
return false;
|
||||
|
||||
if( aObstacle.PointInside( line.CPoint( 0 ) ) ||
|
||||
aObstacle.PointInside( line.CPoint( -1 ) ) )
|
||||
if( aObstacle.PointInside( line.CPoint( 0 ) ) || aObstacle.PointInside( line.CPoint( -1 ) ) )
|
||||
return false;
|
||||
|
||||
SHAPE_LINE_CHAIN::INTERSECTIONS ips, ips2;
|
||||
|
||||
line.Intersect(aObstacle, ips);
|
||||
line.Intersect( aObstacle, ips );
|
||||
|
||||
int nearest_dist = INT_MAX;
|
||||
int farthest_dist = 0;
|
||||
|
||||
SHAPE_LINE_CHAIN::INTERSECTION nearest, farthest;
|
||||
|
||||
for(int i = 0; i < (int) ips.size(); i++)
|
||||
for( int i = 0; i < (int) ips.size(); i++ )
|
||||
{
|
||||
const VECTOR2I p = ips[i].p;
|
||||
int dist = line.PathLength(p);
|
||||
int dist = line.PathLength( p );
|
||||
|
||||
if(dist <= nearest_dist)
|
||||
if( dist <= nearest_dist )
|
||||
{
|
||||
nearest_dist = dist;
|
||||
nearest = ips[i];
|
||||
}
|
||||
|
||||
if(dist >= farthest_dist)
|
||||
if( dist >= farthest_dist )
|
||||
{
|
||||
farthest_dist = dist;
|
||||
farthest = ips[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(ips.size() <= 1 || nearest.p == farthest.p)
|
||||
if( ips.size() <= 1 || nearest.p == farthest.p )
|
||||
{
|
||||
aPre = line;
|
||||
return true;
|
||||
|
@ -213,13 +224,13 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
|
|||
aPre.Simplify();
|
||||
|
||||
aWalk.Clear();
|
||||
aWalk.SetClosed(false);
|
||||
aWalk.SetClosed( false );
|
||||
aWalk.Append( nearest.p );
|
||||
|
||||
int i = nearest.their.Index();
|
||||
|
||||
assert ( nearest.their.Index() >= 0 );
|
||||
assert ( farthest.their.Index() >= 0 );
|
||||
assert( nearest.their.Index() >= 0 );
|
||||
assert( farthest.their.Index() >= 0 );
|
||||
|
||||
assert( nearest_dist <= farthest_dist );
|
||||
|
||||
|
@ -231,14 +242,14 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
|
|||
|
||||
i = i_first;
|
||||
|
||||
while (i != i_last)
|
||||
while( i != i_last )
|
||||
{
|
||||
aWalk.Append(aObstacle.CPoint(i));
|
||||
i += (aCw ? 1 : -1);
|
||||
aWalk.Append( aObstacle.CPoint( i ) );
|
||||
i += ( aCw ? 1 : -1 );
|
||||
|
||||
if (i < 0)
|
||||
if( i < 0 )
|
||||
i = aObstacle.PointCount() - 1;
|
||||
else if (i == aObstacle.PointCount())
|
||||
else if( i == aObstacle.PointCount() )
|
||||
i = 0;
|
||||
}
|
||||
|
||||
|
@ -249,9 +260,11 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
|
|||
aPost.Append( farthest.p );
|
||||
aPost.Append( line.Slice( farthest.our.Index() + 1, -1 ) );
|
||||
aPost.Simplify();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
||||
SHAPE_LINE_CHAIN& aPath,
|
||||
bool aCw ) const
|
||||
|
@ -298,12 +311,12 @@ const PNS_LINE PNS_LINE::ClipToNearestObstacle( PNS_NODE* aNode ) const
|
|||
{
|
||||
PNS_LINE l( *this );
|
||||
|
||||
PNS_NODE::OptObstacle obs = aNode->NearestObstacle( &l );
|
||||
PNS_NODE::OPT_OBSTACLE obs = aNode->NearestObstacle( &l );
|
||||
|
||||
if( obs )
|
||||
{
|
||||
l.RemoveVia();
|
||||
int p = l.Line().Split( obs->ip_first );
|
||||
int p = l.Line().Split( obs->m_ipFirst );
|
||||
l.Line().Remove( p + 1, -1 );
|
||||
}
|
||||
|
||||
|
@ -325,113 +338,121 @@ void PNS_LINE::ShowLinks()
|
|||
printf( "seg %d: %p\n", i, (*m_segmentRefs)[i] );
|
||||
}
|
||||
|
||||
SHAPE_LINE_CHAIN dragCornerInternal ( const SHAPE_LINE_CHAIN& origin, const VECTOR2I& aP )
|
||||
SHAPE_LINE_CHAIN dragCornerInternal( const SHAPE_LINE_CHAIN& aOrigin, const VECTOR2I& aP )
|
||||
{
|
||||
optional<SHAPE_LINE_CHAIN> picked;
|
||||
int i;
|
||||
|
||||
int d = 2;
|
||||
|
||||
if(origin.CSegment(-1).Length() > 100000 * 30) // fixme: constant/parameter?
|
||||
if( aOrigin.CSegment( -1 ).Length() > 100000 * 30 ) // fixme: constant/parameter?
|
||||
d = 1;
|
||||
|
||||
for(i = origin.SegmentCount() - d; i >= 0; i--)
|
||||
for( i = aOrigin.SegmentCount() - d; i >= 0; i-- )
|
||||
{
|
||||
|
||||
DIRECTION_45 d_start (origin.CSegment(i));
|
||||
VECTOR2I p_start = origin.CPoint(i);
|
||||
SHAPE_LINE_CHAIN paths [2];
|
||||
DIRECTION_45 d_start ( aOrigin.CSegment( i ) );
|
||||
VECTOR2I p_start = aOrigin.CPoint( i );
|
||||
SHAPE_LINE_CHAIN paths[2];
|
||||
DIRECTION_45 dirs[2];
|
||||
DIRECTION_45 d_prev = (i > 0 ? DIRECTION_45(origin.CSegment(i-1)) : DIRECTION_45());
|
||||
DIRECTION_45 d_prev = ( i > 0 ? DIRECTION_45( aOrigin.CSegment( i - 1 ) ) : DIRECTION_45() );
|
||||
|
||||
for(int j = 0; j < 2; j++)
|
||||
for( int j = 0; j < 2; j++ )
|
||||
{
|
||||
paths [j] = d_start.BuildInitialTrace( p_start, aP, j );
|
||||
dirs [j] = DIRECTION_45(paths[j].CSegment(0));
|
||||
paths[j] = d_start.BuildInitialTrace( p_start, aP, j );
|
||||
dirs[j] = DIRECTION_45( paths[j].CSegment( 0 ) );
|
||||
}
|
||||
|
||||
|
||||
for( int j = 0; j < 2; j++)
|
||||
if(dirs[j] == d_start)
|
||||
{
|
||||
picked = paths[j];
|
||||
break;
|
||||
}
|
||||
|
||||
if(picked)
|
||||
break;
|
||||
|
||||
for(int j = 0; j < 2; j++)
|
||||
if (dirs[j].IsObtuse(d_prev))
|
||||
for( int j = 0; j < 2; j++ )
|
||||
{
|
||||
if( dirs[j] == d_start )
|
||||
{
|
||||
picked = paths[j];
|
||||
break;
|
||||
}
|
||||
if(picked)
|
||||
break;
|
||||
}
|
||||
|
||||
if( picked )
|
||||
break;
|
||||
|
||||
for( int j = 0; j < 2; j++ )
|
||||
{
|
||||
if( dirs[j].IsObtuse( d_prev ) )
|
||||
{
|
||||
picked = paths[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( picked )
|
||||
break;
|
||||
}
|
||||
|
||||
if(picked)
|
||||
if( picked )
|
||||
{
|
||||
SHAPE_LINE_CHAIN path = origin.Slice(0, i);
|
||||
path.Append(*picked);
|
||||
return path;
|
||||
SHAPE_LINE_CHAIN path = aOrigin.Slice( 0, i );
|
||||
path.Append( *picked );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
return DIRECTION_45().BuildInitialTrace(origin.CPoint(0), aP, true);
|
||||
return DIRECTION_45().BuildInitialTrace( aOrigin.CPoint( 0 ), aP, true );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PNS_LINE::DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
|
||||
{
|
||||
SHAPE_LINE_CHAIN path;
|
||||
|
||||
VECTOR2I snapped = snapDraggedCorner( m_line, aP, aIndex, aSnappingThreshold );
|
||||
|
||||
if( aIndex == 0)
|
||||
if( aIndex == 0 )
|
||||
path = dragCornerInternal( m_line.Reverse(), snapped ).Reverse();
|
||||
else if ( aIndex == m_line.SegmentCount() )
|
||||
path = dragCornerInternal( m_line, snapped );
|
||||
else {
|
||||
else
|
||||
{
|
||||
// fixme: awkward behaviour for "outwards" drags
|
||||
path = dragCornerInternal( m_line.Slice (0, aIndex), snapped );
|
||||
SHAPE_LINE_CHAIN path_rev = dragCornerInternal( m_line.Slice (aIndex, -1).Reverse(), snapped ).Reverse();
|
||||
path.Append(path_rev);
|
||||
path = dragCornerInternal( m_line.Slice( 0, aIndex ), snapped );
|
||||
SHAPE_LINE_CHAIN path_rev = dragCornerInternal( m_line.Slice( aIndex, -1 ).Reverse(),
|
||||
snapped ).Reverse();
|
||||
path.Append( path_rev );
|
||||
}
|
||||
|
||||
path.Simplify();
|
||||
m_line = path;
|
||||
}
|
||||
|
||||
VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const
|
||||
|
||||
VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I& aP,
|
||||
int aIndex, int aThreshold ) const
|
||||
{
|
||||
int s_start = std::max(aIndex - 2, 0);
|
||||
int s_end = std::min(aIndex + 2, aPath.SegmentCount() - 1);
|
||||
int s_start = std::max( aIndex - 2, 0 );
|
||||
int s_end = std::min( aIndex + 2, aPath.SegmentCount() - 1 );
|
||||
|
||||
int i, j;
|
||||
int best_dist = INT_MAX;
|
||||
VECTOR2I best_snap = aP;
|
||||
|
||||
if(aThreshold <= 0)
|
||||
if( aThreshold <= 0 )
|
||||
return aP;
|
||||
|
||||
for(i = s_start; i <= s_end; i++)
|
||||
for( i = s_start; i <= s_end; i++ )
|
||||
{
|
||||
const SEG& a = aPath.CSegment(i);
|
||||
const SEG& a = aPath.CSegment( i );
|
||||
|
||||
for(j = s_start; j < i; j++)
|
||||
for( j = s_start; j < i; j++ )
|
||||
{
|
||||
const SEG& b = aPath.CSegment(j);
|
||||
const SEG& b = aPath.CSegment( j );
|
||||
|
||||
if( ! (DIRECTION_45(a).IsObtuse(DIRECTION_45(b))) )
|
||||
if( !( DIRECTION_45( a ).IsObtuse(DIRECTION_45( b ) ) ) )
|
||||
continue;
|
||||
|
||||
OPT_VECTOR2I ip = a.IntersectLines(b);
|
||||
|
||||
if(ip)
|
||||
if( ip )
|
||||
{
|
||||
int dist = (*ip - aP).EuclideanNorm();
|
||||
int dist = ( *ip - aP ).EuclideanNorm();
|
||||
|
||||
if( dist < aThreshold && dist < best_dist )
|
||||
{
|
||||
best_dist = dist;
|
||||
|
@ -444,40 +465,47 @@ VECTOR2I PNS_LINE::snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTO
|
|||
return best_snap;
|
||||
}
|
||||
|
||||
VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const
|
||||
VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP,
|
||||
int aIndex, int aThreshold ) const
|
||||
{
|
||||
VECTOR2I snap_p[2];
|
||||
DIRECTION_45 dragDir ( aPath.CSegment(aIndex) );
|
||||
int snap_d[2] = {-1, -1};
|
||||
DIRECTION_45 dragDir( aPath.CSegment( aIndex ) );
|
||||
int snap_d[2] = { -1, -1 };
|
||||
|
||||
if( aThreshold == 0 )
|
||||
return aP;
|
||||
|
||||
if(aIndex >= 2)
|
||||
if( aIndex >= 2 )
|
||||
{
|
||||
SEG s = aPath.CSegment(aIndex - 2);
|
||||
if(DIRECTION_45(s) == dragDir)
|
||||
snap_d[0] = s.LineDistance(aP);
|
||||
SEG s = aPath.CSegment( aIndex - 2 );
|
||||
|
||||
if( DIRECTION_45( s ) == dragDir )
|
||||
snap_d[0] = s.LineDistance( aP );
|
||||
|
||||
snap_p[0] = s.A;
|
||||
}
|
||||
|
||||
if(aIndex < aPath.SegmentCount() - 2)
|
||||
if( aIndex < aPath.SegmentCount() - 2 )
|
||||
{
|
||||
SEG s = aPath.CSegment(aIndex + 2);
|
||||
if(DIRECTION_45(s) == dragDir)
|
||||
SEG s = aPath.CSegment( aIndex + 2 );
|
||||
|
||||
if( DIRECTION_45( s ) == dragDir )
|
||||
snap_d[1] = s.LineDistance(aP);
|
||||
|
||||
snap_p[1] = s.A;
|
||||
}
|
||||
|
||||
VECTOR2I best = aP;
|
||||
int minDist = INT_MAX;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
if(snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= aThreshold)
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
if( snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= aThreshold )
|
||||
{
|
||||
minDist = snap_d[i];
|
||||
best = snap_p[i];
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
@ -485,157 +513,166 @@ VECTOR2I PNS_LINE::snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const
|
|||
|
||||
void PNS_LINE::DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold )
|
||||
{
|
||||
SHAPE_LINE_CHAIN path (m_line);
|
||||
VECTOR2I target (aP) ;
|
||||
SHAPE_LINE_CHAIN path( m_line );
|
||||
VECTOR2I target( aP );
|
||||
|
||||
SEG guideA[2], guideB[2];
|
||||
int index = aIndex;
|
||||
|
||||
target = snapToNeighbourSegments( path, aP, aIndex, aSnappingThreshold );
|
||||
|
||||
if(index == 0)
|
||||
if( index == 0 )
|
||||
{
|
||||
path.Insert (0, path.CPoint(0));
|
||||
path.Insert( 0, path.CPoint( 0 ) );
|
||||
index++;
|
||||
}
|
||||
|
||||
if(index == path.SegmentCount()-1)
|
||||
if( index == path.SegmentCount() - 1 )
|
||||
{
|
||||
path.Insert(path.PointCount() - 1, path.CPoint(-1));
|
||||
path.Insert( path.PointCount() - 1, path.CPoint( -1 ) );
|
||||
}
|
||||
|
||||
SEG dragged = path.CSegment(index);
|
||||
DIRECTION_45 drag_dir (dragged);
|
||||
SEG dragged = path.CSegment( index );
|
||||
DIRECTION_45 drag_dir( dragged );
|
||||
|
||||
SEG s_prev = path.CSegment(index - 1);
|
||||
SEG s_next = path.CSegment(index + 1);
|
||||
SEG s_prev = path.CSegment( index - 1 );
|
||||
SEG s_next = path.CSegment( index + 1 );
|
||||
|
||||
DIRECTION_45 dir_prev (s_prev);
|
||||
DIRECTION_45 dir_next (s_next);
|
||||
DIRECTION_45 dir_prev( s_prev );
|
||||
DIRECTION_45 dir_next( s_next );
|
||||
|
||||
if(dir_prev == drag_dir)
|
||||
if( dir_prev == drag_dir )
|
||||
{
|
||||
dir_prev = dir_prev.Left();
|
||||
path.Insert( index, path.CPoint(index) );
|
||||
path.Insert( index, path.CPoint( index ) );
|
||||
index++;
|
||||
}
|
||||
|
||||
if(dir_next == drag_dir)
|
||||
if( dir_next == drag_dir )
|
||||
{
|
||||
dir_next = dir_next.Right();
|
||||
path.Insert( index + 1, path.CPoint(index + 1) );
|
||||
path.Insert( index + 1, path.CPoint( index + 1 ) );
|
||||
}
|
||||
|
||||
|
||||
s_prev = path.CSegment(index - 1);
|
||||
s_next = path.CSegment(index + 1);
|
||||
dragged = path.CSegment(index);
|
||||
s_prev = path.CSegment( index - 1 );
|
||||
s_next = path.CSegment( index + 1 );
|
||||
dragged = path.CSegment( index );
|
||||
|
||||
bool lockEndpointA = true;
|
||||
bool lockEndpointB = true;
|
||||
|
||||
if(aIndex == 0)
|
||||
if( aIndex == 0 )
|
||||
{
|
||||
if(!lockEndpointA)
|
||||
if( !lockEndpointA )
|
||||
guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Right().Right().ToVector() );
|
||||
else {
|
||||
else
|
||||
{
|
||||
guideA[0] = SEG( dragged.A, dragged.A + drag_dir.Right().ToVector() );
|
||||
guideA[1] = SEG( dragged.A, dragged.A + drag_dir.Left().ToVector() );
|
||||
}
|
||||
} else {
|
||||
if(dir_prev.IsObtuse(drag_dir))
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dir_prev.IsObtuse(drag_dir ) )
|
||||
{
|
||||
guideA[0] = SEG( s_prev.A, s_prev.A + drag_dir.Left().ToVector() );
|
||||
guideA[1] = SEG( s_prev.A, s_prev.A + drag_dir.Right().ToVector() );
|
||||
} else
|
||||
guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + dir_prev.ToVector() );
|
||||
guideA[0] = SEG( s_prev.A, s_prev.A + drag_dir.Left().ToVector() );
|
||||
guideA[1] = SEG( s_prev.A, s_prev.A + drag_dir.Right().ToVector() );
|
||||
}
|
||||
else
|
||||
guideA[0] = guideA[1] = SEG( dragged.A, dragged.A + dir_prev.ToVector() );
|
||||
}
|
||||
|
||||
if(aIndex == m_line.SegmentCount() - 1)
|
||||
if( aIndex == m_line.SegmentCount() - 1 )
|
||||
{
|
||||
if(!lockEndpointB)
|
||||
if( !lockEndpointB )
|
||||
guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Right().Right().ToVector() );
|
||||
else {
|
||||
else
|
||||
{
|
||||
guideB[0] = SEG( dragged.B, dragged.B + drag_dir.Right().ToVector() );
|
||||
guideB[1] = SEG( dragged.B, dragged.B + drag_dir.Left().ToVector() );
|
||||
}
|
||||
} else {
|
||||
if(dir_next.IsObtuse(drag_dir))
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dir_next.IsObtuse( drag_dir ) )
|
||||
{
|
||||
guideB[0] = SEG( s_next.B, s_next.B + drag_dir.Left().ToVector() );
|
||||
guideB[1] = SEG( s_next.B, s_next.B + drag_dir.Right().ToVector() );
|
||||
} else
|
||||
guideB[0] = SEG( s_next.B, s_next.B + drag_dir.Left().ToVector() );
|
||||
guideB[1] = SEG( s_next.B, s_next.B + drag_dir.Right().ToVector() );
|
||||
}
|
||||
else
|
||||
guideB[0] = guideB[1] = SEG( dragged.B, dragged.B + dir_next.ToVector() );
|
||||
}
|
||||
|
||||
SEG s_current (target, target + drag_dir.ToVector());
|
||||
SEG s_current( target, target + drag_dir.ToVector() );
|
||||
|
||||
int best_len = INT_MAX;
|
||||
SHAPE_LINE_CHAIN best;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
for(int j = 0; j < 2; j++)
|
||||
for( int j = 0; j < 2; j++ )
|
||||
{
|
||||
OPT_VECTOR2I ip1 = s_current.IntersectLines(guideA[i]);
|
||||
OPT_VECTOR2I ip2 = s_current.IntersectLines(guideB[j]);
|
||||
OPT_VECTOR2I ip1 = s_current.IntersectLines( guideA[i] );
|
||||
OPT_VECTOR2I ip2 = s_current.IntersectLines( guideB[j] );
|
||||
|
||||
SHAPE_LINE_CHAIN np;
|
||||
SHAPE_LINE_CHAIN np;
|
||||
|
||||
if(!ip1 || !ip2)
|
||||
continue;
|
||||
if( !ip1 || !ip2 )
|
||||
continue;
|
||||
|
||||
SEG s1 ( s_prev.A, *ip1 );
|
||||
SEG s2 ( *ip1, *ip2 );
|
||||
SEG s3 ( *ip2, s_next.B );
|
||||
SEG s1( s_prev.A, *ip1 );
|
||||
SEG s2( *ip1, *ip2 );
|
||||
SEG s3( *ip2, s_next.B );
|
||||
|
||||
OPT_VECTOR2I ip;
|
||||
OPT_VECTOR2I ip;
|
||||
|
||||
if(ip = s1.Intersect(s_next))
|
||||
{
|
||||
np.Append ( s1.A );
|
||||
np.Append ( *ip );
|
||||
np.Append ( s_next.B );
|
||||
} else if(ip = s3.Intersect(s_prev))
|
||||
{
|
||||
np.Append ( s_prev.A );
|
||||
np.Append ( *ip );
|
||||
np.Append ( s3.B );
|
||||
} else if(ip = s1.Intersect(s3))
|
||||
{
|
||||
np.Append( s_prev.A );
|
||||
np.Append( *ip );
|
||||
np.Append( s_next.B );
|
||||
} else {
|
||||
np.Append( s_prev.A );
|
||||
np.Append( *ip1 );
|
||||
np.Append( *ip2 );
|
||||
np.Append( s_next.B );
|
||||
}
|
||||
if( ip = s1.Intersect( s_next ) )
|
||||
{
|
||||
np.Append ( s1.A );
|
||||
np.Append ( *ip );
|
||||
np.Append ( s_next.B );
|
||||
}
|
||||
else if( ip = s3.Intersect( s_prev ) )
|
||||
{
|
||||
np.Append ( s_prev.A );
|
||||
np.Append ( *ip );
|
||||
np.Append ( s3.B );
|
||||
}
|
||||
else if( ip = s1.Intersect( s3 ) )
|
||||
{
|
||||
np.Append( s_prev.A );
|
||||
np.Append( *ip );
|
||||
np.Append( s_next.B );
|
||||
}
|
||||
else
|
||||
{
|
||||
np.Append( s_prev.A );
|
||||
np.Append( *ip1 );
|
||||
np.Append( *ip2 );
|
||||
np.Append( s_next.B );
|
||||
}
|
||||
|
||||
if(np.Length() < best_len)
|
||||
{
|
||||
best_len = np.Length();
|
||||
best = np;
|
||||
}
|
||||
|
||||
if( np.Length() < best_len )
|
||||
{
|
||||
best_len = np.Length();
|
||||
best = np;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!lockEndpointA && aIndex == 0)
|
||||
best.Remove(0, 0);
|
||||
if(!lockEndpointB && aIndex == m_line.SegmentCount() - 1)
|
||||
best.Remove(-1, -1);
|
||||
|
||||
|
||||
if(m_line.PointCount() == 1)
|
||||
if( !lockEndpointA && aIndex == 0 )
|
||||
best.Remove( 0, 0 );
|
||||
if( !lockEndpointB && aIndex == m_line.SegmentCount() - 1 )
|
||||
best.Remove( -1, -1 );
|
||||
|
||||
if( m_line.PointCount() == 1 )
|
||||
m_line = best;
|
||||
else if (aIndex == 0)
|
||||
m_line.Replace(0, 1, best);
|
||||
else if (aIndex == m_line.SegmentCount() - 1)
|
||||
m_line.Replace(-2, -1, best);
|
||||
else if( aIndex == 0 )
|
||||
m_line.Replace( 0, 1, best );
|
||||
else if( aIndex == m_line.SegmentCount() - 1 )
|
||||
m_line.Replace( -2, -1, best );
|
||||
else
|
||||
m_line.Replace(aIndex, aIndex + 1, best);
|
||||
m_line.Replace( aIndex, aIndex + 1, best );
|
||||
|
||||
m_line.Simplify();
|
||||
}
|
||||
|
@ -643,21 +680,23 @@ void PNS_LINE::DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThresh
|
|||
|
||||
bool PNS_LINE::CompareGeometry( const PNS_LINE& aOther )
|
||||
{
|
||||
return m_line.CompareGeometry(aOther.m_line);
|
||||
return m_line.CompareGeometry( aOther.m_line );
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::Reverse()
|
||||
{
|
||||
m_line = m_line.Reverse();
|
||||
if(m_segmentRefs)
|
||||
std::reverse(m_segmentRefs->begin(), m_segmentRefs->end() );
|
||||
m_line = m_line.Reverse();
|
||||
|
||||
if( m_segmentRefs )
|
||||
std::reverse( m_segmentRefs->begin(), m_segmentRefs->end() );
|
||||
}
|
||||
|
||||
void PNS_LINE::AppendVia(const PNS_VIA& aVia)
|
||||
|
||||
void PNS_LINE::AppendVia( const PNS_VIA& aVia )
|
||||
{
|
||||
if(aVia.Pos() == m_line.CPoint(0))
|
||||
if( aVia.Pos() == m_line.CPoint( 0 ) )
|
||||
{
|
||||
|
||||
Reverse();
|
||||
}
|
||||
|
||||
|
@ -666,62 +705,73 @@ void PNS_LINE::AppendVia(const PNS_VIA& aVia)
|
|||
m_via.SetNet( m_net );
|
||||
}
|
||||
|
||||
void PNS_LINE::SetRank(int aRank)
|
||||
|
||||
void PNS_LINE::SetRank( int aRank )
|
||||
{
|
||||
m_rank = aRank;
|
||||
if(m_segmentRefs)
|
||||
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs )
|
||||
s->SetRank(aRank);
|
||||
BOOST_FOREACH( PNS_SEGMENT* s, *m_segmentRefs )
|
||||
s->SetRank( aRank );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PNS_LINE::Rank() const
|
||||
{
|
||||
int min_rank = INT_MAX;
|
||||
int rank;
|
||||
if(m_segmentRefs)
|
||||
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
BOOST_FOREACH( PNS_SEGMENT *s, *m_segmentRefs )
|
||||
min_rank = std::min(min_rank, s->Rank());
|
||||
rank = (min_rank == INT_MAX) ? -1 : min_rank;
|
||||
} else {
|
||||
min_rank = std::min( min_rank, s->Rank() );
|
||||
rank = ( min_rank == INT_MAX ) ? -1 : min_rank;
|
||||
}
|
||||
else
|
||||
{
|
||||
rank = m_rank;
|
||||
}
|
||||
|
||||
return rank;
|
||||
}
|
||||
|
||||
void PNS_LINE::ClipVertexRange ( int aStart, int aEnd )
|
||||
|
||||
void PNS_LINE::ClipVertexRange( int aStart, int aEnd )
|
||||
{
|
||||
m_line = m_line.Slice (aStart, aEnd);
|
||||
m_line = m_line.Slice( aStart, aEnd );
|
||||
|
||||
if(m_segmentRefs)
|
||||
if( m_segmentRefs )
|
||||
{
|
||||
SegmentRefs *snew = new SegmentRefs( m_segmentRefs->begin() + aStart, m_segmentRefs->begin() + aEnd );
|
||||
SEGMENT_REFS* snew = new SEGMENT_REFS( m_segmentRefs->begin() + aStart,
|
||||
m_segmentRefs->begin() + aEnd );
|
||||
|
||||
delete m_segmentRefs;
|
||||
m_segmentRefs = snew;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE::HasLoops() const
|
||||
{
|
||||
|
||||
for(int i = 0; i < PointCount(); i++)
|
||||
for(int j = 0; j < PointCount(); j++)
|
||||
for( int i = 0; i < PointCount(); i++ )
|
||||
{
|
||||
for( int j = 0; j < PointCount(); j++ )
|
||||
{
|
||||
if( (std::abs(i-j) > 1) && CPoint(i) == CPoint(j))
|
||||
if( ( std::abs( i - j ) > 1 ) && CPoint( i ) == CPoint( j ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE::ClearSegmentLinks()
|
||||
{
|
||||
if(m_segmentRefs)
|
||||
if( m_segmentRefs )
|
||||
delete m_segmentRefs;
|
||||
|
||||
m_segmentRefs = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,19 +57,18 @@ class PNS_VIA;
|
|||
class PNS_LINE : public PNS_ITEM
|
||||
{
|
||||
public:
|
||||
typedef std::vector<PNS_SEGMENT*> SegmentRefs;
|
||||
typedef std::vector<PNS_SEGMENT*> SEGMENT_REFS;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Makes an empty line.
|
||||
*/
|
||||
PNS_LINE() : PNS_ITEM (LINE)
|
||||
PNS_LINE() : PNS_ITEM( LINE )
|
||||
{
|
||||
m_segmentRefs = NULL;
|
||||
m_hasVia = false;
|
||||
}
|
||||
|
||||
|
||||
PNS_LINE( const PNS_LINE& aOther ) ;
|
||||
|
||||
/**
|
||||
|
@ -77,7 +76,6 @@ public:
|
|||
* Copies properties (net, layers, etc.) from a base line and replaces the shape
|
||||
* by another
|
||||
**/
|
||||
|
||||
PNS_LINE( const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine ) :
|
||||
PNS_ITEM( aBase ),
|
||||
m_line( aLine ),
|
||||
|
@ -92,12 +90,12 @@ public:
|
|||
~PNS_LINE();
|
||||
|
||||
/// @copydoc PNS_ITEM::Clone()
|
||||
virtual PNS_LINE* Clone( ) const;
|
||||
virtual PNS_LINE* Clone() const;
|
||||
|
||||
const PNS_LINE& operator= (const PNS_LINE& aOther);
|
||||
const PNS_LINE& operator=( const PNS_LINE& aOther );
|
||||
|
||||
///> Assigns a shape to the line (a polyline/line chain)
|
||||
void SetShape ( const SHAPE_LINE_CHAIN& aLine )
|
||||
void SetShape( const SHAPE_LINE_CHAIN& aLine )
|
||||
{
|
||||
m_line = aLine;
|
||||
}
|
||||
|
@ -135,13 +133,13 @@ public:
|
|||
///> Returns the aIdx-th point of the line
|
||||
const VECTOR2I& CPoint( int aIdx ) const
|
||||
{
|
||||
return m_line.CPoint(aIdx);
|
||||
return m_line.CPoint( aIdx );
|
||||
}
|
||||
|
||||
///> Returns the aIdx-th segment of the line
|
||||
const SEG CSegment (int aIdx ) const
|
||||
const SEG CSegment( int aIdx ) const
|
||||
{
|
||||
return m_line.CSegment(aIdx);
|
||||
return m_line.CSegment( aIdx );
|
||||
}
|
||||
|
||||
///> Sets line width
|
||||
|
@ -169,14 +167,14 @@ public:
|
|||
void LinkSegment( PNS_SEGMENT* aSeg )
|
||||
{
|
||||
if( !m_segmentRefs )
|
||||
m_segmentRefs = new SegmentRefs();
|
||||
m_segmentRefs = new SEGMENT_REFS();
|
||||
|
||||
m_segmentRefs->push_back( aSeg );
|
||||
}
|
||||
|
||||
///> Returns the list of segments from the owning node that constitute this
|
||||
///> line (or NULL if the line is not linked)
|
||||
SegmentRefs* LinkedSegments()
|
||||
SEGMENT_REFS* LinkedSegments()
|
||||
{
|
||||
return m_segmentRefs;
|
||||
}
|
||||
|
@ -195,9 +193,11 @@ public:
|
|||
void ClearSegmentLinks();
|
||||
|
||||
///> Returns the number of segments that were assembled together to form this line.
|
||||
int LinkCount() const {
|
||||
if(!m_segmentRefs)
|
||||
int LinkCount() const
|
||||
{
|
||||
if( !m_segmentRefs )
|
||||
return -1;
|
||||
|
||||
return m_segmentRefs->size();
|
||||
}
|
||||
|
||||
|
@ -208,7 +208,6 @@ public:
|
|||
///> Clips the line to a given range of vertices.
|
||||
void ClipVertexRange ( int aStart, int aEnd );
|
||||
|
||||
|
||||
///> Returns the number of corners of angles specified by mask aAngles.
|
||||
int CountCorners( int aAngles );
|
||||
|
||||
|
@ -218,12 +217,11 @@ public:
|
|||
///> aWalkaroundPath = path around the obstacle
|
||||
///> aPostPath = past from obstacle till the end
|
||||
///> aCW = whether to walk around in clockwise or counter-clockwise direction.
|
||||
|
||||
bool Walkaround( SHAPE_LINE_CHAIN obstacle,
|
||||
SHAPE_LINE_CHAIN& pre,
|
||||
SHAPE_LINE_CHAIN& walk,
|
||||
SHAPE_LINE_CHAIN& post,
|
||||
bool cw ) const;
|
||||
bool Walkaround( SHAPE_LINE_CHAIN aObstacle,
|
||||
SHAPE_LINE_CHAIN& aPre,
|
||||
SHAPE_LINE_CHAIN& aWalk,
|
||||
SHAPE_LINE_CHAIN& aPost,
|
||||
bool aCw ) const;
|
||||
|
||||
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
|
||||
SHAPE_LINE_CHAIN& aPath,
|
||||
|
@ -241,29 +239,31 @@ public:
|
|||
|
||||
const PNS_VIA& Via() const { return m_via; }
|
||||
|
||||
virtual void Mark(int aMarker);
|
||||
virtual void Mark( int aMarker );
|
||||
virtual void Unmark ();
|
||||
virtual int Marker() const;
|
||||
|
||||
void DragSegment ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
|
||||
void DragCorner ( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
|
||||
void DragSegment( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
|
||||
void DragCorner( const VECTOR2I& aP, int aIndex, int aSnappingThreshold = 0 );
|
||||
|
||||
void SetRank ( int aRank );
|
||||
void SetRank( int aRank );
|
||||
int Rank() const;
|
||||
|
||||
bool HasLoops() const;
|
||||
|
||||
private:
|
||||
VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP,
|
||||
int aIndex, int aThreshold) const;
|
||||
|
||||
VECTOR2I snapToNeighbourSegments( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold) const;
|
||||
VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP, int aIndex, int aThreshold ) const;
|
||||
VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I &aP,
|
||||
int aIndex, int aThreshold ) const;
|
||||
|
||||
///> Copies m_segmentRefs from the line aParent.
|
||||
void copyLinks( const PNS_LINE *aParent ) ;
|
||||
void copyLinks( const PNS_LINE* aParent ) ;
|
||||
|
||||
///> List of segments in the owning PNS_NODE (PNS_ITEM::m_owner) that constitute this line, or NULL
|
||||
///> if the line is not a part of any node.
|
||||
SegmentRefs* m_segmentRefs;
|
||||
SEGMENT_REFS* m_segmentRefs;
|
||||
|
||||
///> The actual shape of the line
|
||||
SHAPE_LINE_CHAIN m_line;
|
||||
|
|
|
@ -44,7 +44,8 @@ PNS_LINE_PLACER::PNS_LINE_PLACER( PNS_ROUTER* aRouter ) :
|
|||
m_world = NULL;
|
||||
m_shove = NULL;
|
||||
m_currentNode = NULL;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
PNS_LINE_PLACER::~PNS_LINE_PLACER()
|
||||
{
|
||||
|
@ -52,11 +53,13 @@ PNS_LINE_PLACER::~PNS_LINE_PLACER()
|
|||
delete m_shove;
|
||||
}
|
||||
|
||||
void PNS_LINE_PLACER::setWorld ( PNS_NODE *aWorld )
|
||||
|
||||
void PNS_LINE_PLACER::setWorld ( PNS_NODE* aWorld )
|
||||
{
|
||||
m_world = aWorld;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::AddVia( bool aEnabled, int aDiameter, int aDrill )
|
||||
{
|
||||
m_viaDiameter = aDiameter;
|
||||
|
@ -64,11 +67,10 @@ void PNS_LINE_PLACER::AddVia( bool aEnabled, int aDiameter, int aDrill )
|
|||
m_placingVia = aEnabled;
|
||||
}
|
||||
|
||||
void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet,
|
||||
int aWidth, int aLayer )
|
||||
|
||||
void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet, int aWidth, int aLayer )
|
||||
{
|
||||
|
||||
assert(m_world != NULL);
|
||||
assert( m_world != NULL );
|
||||
|
||||
m_direction = m_initial_direction;
|
||||
TRACE( 1, "world %p, intitial-direction %s layer %d\n",
|
||||
|
@ -89,14 +91,14 @@ void PNS_LINE_PLACER::startPlacement( const VECTOR2I& aStart, int aNet,
|
|||
|
||||
m_currentMode = Settings().Mode();
|
||||
|
||||
if(m_shove)
|
||||
if( m_shove )
|
||||
delete m_shove;
|
||||
|
||||
m_shove = NULL;
|
||||
|
||||
if(m_currentMode == RM_Shove || m_currentMode == RM_Smart)
|
||||
if( m_currentMode == RM_Shove || m_currentMode == RM_Smart )
|
||||
{
|
||||
m_shove = new PNS_SHOVE( m_world -> Branch(), Router() );
|
||||
m_shove = new PNS_SHOVE( m_world->Branch(), Router() );
|
||||
}
|
||||
|
||||
m_placingVia = false;
|
||||
|
@ -107,8 +109,8 @@ void PNS_LINE_PLACER::setInitialDirection( const DIRECTION_45& aDirection )
|
|||
{
|
||||
m_initial_direction = aDirection;
|
||||
|
||||
if( m_tail.SegmentCount() == 0 )
|
||||
m_direction = aDirection;
|
||||
if( m_tail.SegmentCount() == 0 )
|
||||
m_direction = aDirection;
|
||||
}
|
||||
|
||||
|
||||
|
@ -154,6 +156,7 @@ bool PNS_LINE_PLACER::handleSelfIntersections()
|
|||
m_direction = m_initial_direction;
|
||||
tail.Clear();
|
||||
head.Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -176,7 +179,7 @@ bool PNS_LINE_PLACER::handlePullback()
|
|||
SHAPE_LINE_CHAIN& head = m_head.Line();
|
||||
SHAPE_LINE_CHAIN& tail = m_tail.Line();
|
||||
|
||||
if(head.PointCount() < 2)
|
||||
if( head.PointCount() < 2 )
|
||||
return false;
|
||||
|
||||
int n = tail.PointCount();
|
||||
|
@ -201,7 +204,7 @@ bool PNS_LINE_PLACER::handlePullback()
|
|||
// case 2: regardless of the current routing direction, if the tail/head
|
||||
// extremities form an acute or right angle, reduce the tail by one segment
|
||||
// (and hope that further iterations) will result with a cleaner trace
|
||||
bool pullback_2 = (angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE);
|
||||
bool pullback_2 = ( angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE );
|
||||
|
||||
if( pullback_1 || pullback_2 )
|
||||
{
|
||||
|
@ -237,7 +240,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
|
|||
|
||||
int n = tail.SegmentCount();
|
||||
|
||||
if(head.SegmentCount() < 1)
|
||||
if( head.SegmentCount() < 1 )
|
||||
return false;
|
||||
|
||||
// Don't attempt this for too short tails
|
||||
|
@ -294,10 +297,10 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
|
|||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::checkObtusity( const SEG& a, const SEG& b ) const
|
||||
bool PNS_LINE_PLACER::checkObtusity( const SEG& aA, const SEG& aB ) const
|
||||
{
|
||||
const DIRECTION_45 dir_a( a );
|
||||
const DIRECTION_45 dir_b( b );
|
||||
const DIRECTION_45 dir_a( aA );
|
||||
const DIRECTION_45 dir_b( aB );
|
||||
|
||||
return dir_a.IsObtuse( dir_b ) || dir_a == dir_b;
|
||||
}
|
||||
|
@ -399,6 +402,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||
{
|
||||
SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP );
|
||||
|
@ -412,27 +416,30 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
walkaround.SetSolidsOnly( false );
|
||||
walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
|
||||
|
||||
PNS_WALKAROUND::WalkaroundStatus wf = walkaround.Route( initTrack, walkFull, false );
|
||||
PNS_WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
|
||||
|
||||
switch(Settings().OptimizerEffort())
|
||||
switch( Settings().OptimizerEffort() )
|
||||
{
|
||||
case OE_Low:
|
||||
case OE_LOW:
|
||||
effort = 0;
|
||||
break;
|
||||
case OE_Medium:
|
||||
case OE_Full:
|
||||
|
||||
case OE_MEDIUM:
|
||||
case OE_FULL:
|
||||
effort = PNS_OPTIMIZER::MERGE_SEGMENTS;
|
||||
break;
|
||||
}
|
||||
if(Settings().SmartPads())
|
||||
|
||||
if( Settings().SmartPads() )
|
||||
effort |= PNS_OPTIMIZER::SMART_PADS;
|
||||
|
||||
if( wf == PNS_WALKAROUND::STUCK )
|
||||
{
|
||||
walkFull = walkFull.ClipToNearestObstacle( m_currentNode );
|
||||
rv = true;
|
||||
|
||||
} else if( m_placingVia && viaOk ) {
|
||||
}
|
||||
else if( m_placingVia && viaOk )
|
||||
{
|
||||
PNS_LAYERSET allLayers( 0, 15 );
|
||||
PNS_VIA v1( walkFull.CPoint( -1 ), allLayers, m_viaDiameter );
|
||||
walkFull.AppendVia( v1 );
|
||||
|
@ -440,7 +447,7 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
|
||||
PNS_OPTIMIZER::Optimize( &walkFull, effort, m_currentNode );
|
||||
|
||||
if( m_currentNode->CheckColliding(&walkFull) )
|
||||
if( m_currentNode->CheckColliding( &walkFull ) )
|
||||
{
|
||||
TRACEn(0, "strange, walk line colliding\n");
|
||||
}
|
||||
|
@ -451,9 +458,10 @@ bool PNS_LINE_PLACER::rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
return rv;
|
||||
}
|
||||
|
||||
bool PNS_LINE_PLACER::rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||
|
||||
bool PNS_LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||
{
|
||||
m_head.SetShape ( m_direction.BuildInitialTrace( m_p_start, aP ) );
|
||||
m_head.SetShape( m_direction.BuildInitialTrace( m_p_start, aP ) );
|
||||
|
||||
if( m_placingVia )
|
||||
{
|
||||
|
@ -461,12 +469,13 @@ bool PNS_LINE_PLACER::rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
PNS_VIA v1( m_head.CPoint( -1 ), allLayers, m_viaDiameter );
|
||||
m_head.AppendVia( v1 );
|
||||
}
|
||||
|
||||
|
||||
aNewHead = m_head;
|
||||
|
||||
return m_currentNode->CheckColliding( &m_head );
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||
{
|
||||
SHAPE_LINE_CHAIN line = m_direction.BuildInitialTrace( m_p_start, aP );
|
||||
|
@ -482,16 +491,16 @@ bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
|
||||
walkaround.SetSolidsOnly( true );
|
||||
walkaround.SetIterationLimit( 10 );
|
||||
PNS_WALKAROUND::WalkaroundStatus stat_solids = walkaround.Route( initTrack, walkSolids );
|
||||
PNS_WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids );
|
||||
|
||||
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_SEGMENTS );
|
||||
optimizer.SetCollisionMask ( PNS_ITEM::SOLID );
|
||||
optimizer.Optimize( &walkSolids );
|
||||
|
||||
if( stat_solids == PNS_WALKAROUND::DONE )
|
||||
l2 = walkSolids;
|
||||
else
|
||||
l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() );
|
||||
l2 = walkSolids;
|
||||
else
|
||||
l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() );
|
||||
|
||||
PNS_LINE l( m_tail );
|
||||
l.Line().Append( l2.CLine() );
|
||||
|
@ -513,43 +522,43 @@ bool PNS_LINE_PLACER::rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
|
||||
// in certain, uncommon cases there may be loops in the head+tail, In such case, we don't shove to avoid
|
||||
// screwing up the database.
|
||||
if ( l.HasLoops() )
|
||||
if( l.HasLoops() )
|
||||
{
|
||||
aNewHead = m_head;
|
||||
return false;
|
||||
}
|
||||
|
||||
PNS_SHOVE::ShoveStatus status = m_shove->ShoveLines( l );
|
||||
PNS_SHOVE::SHOVE_STATUS status = m_shove->ShoveLines( l );
|
||||
|
||||
m_currentNode = m_shove->CurrentNode();
|
||||
|
||||
if( status == PNS_SHOVE::SH_OK )
|
||||
{
|
||||
optimizer.SetWorld( m_currentNode );
|
||||
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
|
||||
optimizer.SetCollisionMask( PNS_ITEM::ANY );
|
||||
optimizer.Optimize( &l2 );
|
||||
{
|
||||
optimizer.SetWorld( m_currentNode );
|
||||
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
|
||||
optimizer.SetCollisionMask( PNS_ITEM::ANY );
|
||||
optimizer.Optimize( &l2 );
|
||||
|
||||
aNewHead = l2;
|
||||
aNewHead = l2;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
walkaround.SetWorld( m_currentNode );
|
||||
walkaround.SetSolidsOnly( false );
|
||||
walkaround.SetIterationLimit( 10 );
|
||||
walkaround.SetApproachCursor( true, aP );
|
||||
walkaround.Route( initTrack, l2 );
|
||||
aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() );
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
walkaround.SetWorld( m_currentNode );
|
||||
walkaround.SetSolidsOnly( false );
|
||||
walkaround.SetIterationLimit( 10 );
|
||||
walkaround.SetApproachCursor( true, aP );
|
||||
walkaround.Route( initTrack, l2 );
|
||||
aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||
{
|
||||
switch( m_currentMode )
|
||||
|
@ -570,18 +579,18 @@ bool PNS_LINE_PLACER::routeHead( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
|
||||
bool PNS_LINE_PLACER::optimizeTailHeadTransition()
|
||||
{
|
||||
|
||||
PNS_LINE tmp = Trace();
|
||||
|
||||
if(PNS_OPTIMIZER::Optimize(&tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode))
|
||||
if( PNS_OPTIMIZER::Optimize( &tmp, PNS_OPTIMIZER::FANOUT_CLEANUP, m_currentNode ) )
|
||||
{
|
||||
if(tmp.SegmentCount() < 1)
|
||||
if( tmp.SegmentCount() < 1 )
|
||||
return false;
|
||||
|
||||
m_head = tmp;
|
||||
m_p_start = tmp.CLine().CPoint( 0 );
|
||||
m_direction = DIRECTION_45( tmp.CSegment( 0 ) );
|
||||
m_tail.Line().Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -611,7 +620,7 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
|
|||
// If so, replace the (threshold) last tail points and the head with
|
||||
// the optimized line
|
||||
|
||||
if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode))
|
||||
if( PNS_OPTIMIZER::Optimize( &new_head, PNS_OPTIMIZER::MERGE_OBTUSE, m_currentNode ) )
|
||||
{
|
||||
PNS_LINE tmp( m_tail, opt_line );
|
||||
|
||||
|
@ -702,22 +711,26 @@ const PNS_LINE PNS_LINE_PLACER::Trace() const
|
|||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
const PNS_ITEMSET PNS_LINE_PLACER::Traces()
|
||||
{
|
||||
m_currentTrace = Trace();
|
||||
return PNS_ITEMSET( &m_currentTrace );
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::FlipPosture()
|
||||
{
|
||||
m_initial_direction = m_initial_direction.Right();
|
||||
m_direction = m_direction.Right();
|
||||
}
|
||||
|
||||
PNS_NODE* PNS_LINE_PLACER::CurrentNode(bool aLoopsRemoved) const
|
||||
|
||||
PNS_NODE* PNS_LINE_PLACER::CurrentNode( bool aLoopsRemoved ) const
|
||||
{
|
||||
if(aLoopsRemoved && m_lastNode)
|
||||
if( aLoopsRemoved && m_lastNode )
|
||||
return m_lastNode;
|
||||
|
||||
return m_currentNode;
|
||||
}
|
||||
|
||||
|
@ -747,16 +760,19 @@ void PNS_LINE_PLACER::splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, co
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::SetLayer(int aLayer)
|
||||
{
|
||||
m_currentLayer = aLayer;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::SetWidth(int aWidth)
|
||||
{
|
||||
m_currentWidth = aWidth;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
||||
{
|
||||
VECTOR2I p( aP );
|
||||
|
@ -783,7 +799,6 @@ void PNS_LINE_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
|||
m_currentEnd = p;
|
||||
m_currentNet = net;
|
||||
|
||||
|
||||
PNS_NODE *rootNode = Router()->GetWorld()->Branch();
|
||||
|
||||
if( splitSeg )
|
||||
|
@ -801,7 +816,7 @@ void PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
|||
VECTOR2I p = aP;
|
||||
int eiDepth = -1;
|
||||
|
||||
if(aEndItem && aEndItem->Owner())
|
||||
if( aEndItem && aEndItem->Owner() )
|
||||
eiDepth = aEndItem->Owner()->Depth();
|
||||
|
||||
if( m_lastNode )
|
||||
|
@ -814,26 +829,27 @@ void PNS_LINE_PLACER::Move( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
|||
|
||||
current = Trace();
|
||||
|
||||
if(!current.PointCount())
|
||||
if( !current.PointCount() )
|
||||
m_currentEnd = m_p_start;
|
||||
else
|
||||
m_currentEnd = current.CLine().CPoint(-1);
|
||||
|
||||
|
||||
PNS_NODE *latestNode = m_currentNode;
|
||||
m_lastNode = latestNode->Branch();
|
||||
|
||||
|
||||
if(eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() && current.CPoint(-1) == aP)
|
||||
if( eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth &&
|
||||
current.SegmentCount() && current.CPoint( -1 ) == aP )
|
||||
{
|
||||
splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint(-1) );
|
||||
if(Settings().RemoveLoops())
|
||||
splitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
|
||||
|
||||
if( Settings().RemoveLoops() )
|
||||
removeLoops( m_lastNode, ¤t );
|
||||
}
|
||||
|
||||
updateLeadingRatLine();
|
||||
}
|
||||
|
||||
|
||||
bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
||||
{
|
||||
bool realEnd = false;
|
||||
|
@ -861,13 +877,11 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
|||
if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() )
|
||||
realEnd = true;
|
||||
|
||||
|
||||
if(realEnd || m_placingVia)
|
||||
if( realEnd || m_placingVia )
|
||||
lastV = l.SegmentCount();
|
||||
else
|
||||
lastV = std::max( 1, l.SegmentCount() - 1 );
|
||||
|
||||
|
||||
lastV = std::max( 1, l.SegmentCount() - 1 );
|
||||
|
||||
PNS_SEGMENT* lastSeg = NULL;
|
||||
|
||||
for( int i = 0; i < lastV; i++ )
|
||||
|
@ -883,14 +897,14 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
|||
if( pl.EndsWithVia() )
|
||||
m_lastNode->Add( pl.Via().Clone() );
|
||||
|
||||
if(realEnd)
|
||||
if( realEnd )
|
||||
simplifyNewLine ( m_lastNode, lastSeg );
|
||||
|
||||
Router()->CommitRouting ( m_lastNode );
|
||||
|
||||
m_lastNode = NULL;
|
||||
|
||||
if(!realEnd)
|
||||
if( !realEnd )
|
||||
{
|
||||
setInitialDirection( d_last );
|
||||
VECTOR2I p_start = m_placingVia ? p_last : p_pre_last;
|
||||
|
@ -908,20 +922,19 @@ bool PNS_LINE_PLACER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
|||
return realEnd;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
|
||||
{
|
||||
if(!aLatest->SegmentCount())
|
||||
if( !aLatest->SegmentCount() )
|
||||
return;
|
||||
|
||||
aNode->Add( aLatest, true );
|
||||
|
||||
for(int s = 0; s < aLatest->SegmentCount(); s++ )
|
||||
for( int s = 0; s < aLatest->SegmentCount(); s++ )
|
||||
{
|
||||
PNS_SEGMENT *seg = (*aLatest->LinkedSegments())[s];
|
||||
|
||||
PNS_LINE* ourLine = aNode->AssembleLine( seg ) ;
|
||||
PNS_SEGMENT *seg = ( *aLatest->LinkedSegments() )[s];
|
||||
PNS_LINE* ourLine = aNode->AssembleLine( seg );
|
||||
PNS_JOINT a, b;
|
||||
|
||||
std::vector<PNS_LINE*> lines;
|
||||
|
||||
aNode->FindLineEnds( ourLine, a, b );
|
||||
|
@ -940,19 +953,19 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
|
|||
{
|
||||
total++;
|
||||
|
||||
if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() )
|
||||
if( !( line->ContainsSegment( seg ) ) && line->SegmentCount() )
|
||||
{
|
||||
Router()->DisplayDebugLine ( line->CLine(), -1, 10000 );
|
||||
|
||||
for(int i = 0; i < line->PointCount(); i++ )
|
||||
Router()->DisplayDebugPoint ( line->CPoint(i), -1 );
|
||||
for( int i = 0; i < line->PointCount(); i++ )
|
||||
Router()->DisplayDebugPoint( line->CPoint( i ), -1 );
|
||||
|
||||
aNode->Remove( line );
|
||||
removedCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE(0, "total segs removed: %d/%d\n", removedCount % total);
|
||||
TRACE( 0, "total segs removed: %d/%d\n", removedCount % total );
|
||||
|
||||
delete ourLine;
|
||||
}
|
||||
|
@ -960,13 +973,15 @@ void PNS_LINE_PLACER::removeLoops( PNS_NODE* aNode, PNS_LINE* aLatest )
|
|||
aNode->Remove( aLatest );
|
||||
}
|
||||
|
||||
void PNS_LINE_PLACER::simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest )
|
||||
|
||||
void PNS_LINE_PLACER::simplifyNewLine( PNS_NODE* aNode, PNS_SEGMENT* aLatest )
|
||||
{
|
||||
PNS_LINE *l = aNode->AssembleLine( aLatest) ;
|
||||
PNS_LINE* l = aNode->AssembleLine( aLatest );
|
||||
SHAPE_LINE_CHAIN simplified ( l->CLine() );
|
||||
|
||||
simplified.Simplify();
|
||||
|
||||
if(simplified.PointCount() != l->PointCount())
|
||||
if( simplified.PointCount() != l->PointCount() )
|
||||
{
|
||||
std::auto_ptr<PNS_LINE> lnew ( l->Clone() );
|
||||
aNode -> Remove(l);
|
||||
|
@ -975,6 +990,7 @@ void PNS_LINE_PLACER::simplifyNewLine ( PNS_NODE *aNode, PNS_SEGMENT *aLatest )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings )
|
||||
{
|
||||
int trackWidth = aSettings.GetTrackWidth();
|
||||
|
@ -986,29 +1002,31 @@ void PNS_LINE_PLACER::UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings )
|
|||
m_viaDrill = aSettings.GetViaDrill();
|
||||
}
|
||||
|
||||
|
||||
void PNS_LINE_PLACER::updateLeadingRatLine()
|
||||
{
|
||||
PNS_LINE current = Trace();
|
||||
|
||||
if(! current.PointCount() )
|
||||
if( !current.PointCount() )
|
||||
return;
|
||||
|
||||
std::auto_ptr<PNS_NODE> tmpNode ( m_lastNode->Branch() );
|
||||
tmpNode->Add( ¤t );
|
||||
|
||||
PNS_JOINT *jt = tmpNode->FindJoint( current.CPoint(-1), current.Layers().Start(), current.Net() );
|
||||
|
||||
if(!jt)
|
||||
PNS_JOINT *jt = tmpNode->FindJoint( current.CPoint( -1 ),
|
||||
current.Layers().Start(), current.Net() );
|
||||
|
||||
if( !jt )
|
||||
return;
|
||||
|
||||
int anchor;
|
||||
PNS_ITEM *it = tmpNode->NearestUnconnectedItem ( jt, &anchor );
|
||||
PNS_ITEM *it = tmpNode->NearestUnconnectedItem( jt, &anchor );
|
||||
|
||||
if(it)
|
||||
if( it )
|
||||
{
|
||||
SHAPE_LINE_CHAIN lc;
|
||||
lc.Append ( current.CPoint(-1) );
|
||||
lc.Append ( it->Anchor(anchor) );
|
||||
lc.Append ( current.CPoint( -1 ) );
|
||||
lc.Append ( it->Anchor( anchor ) );
|
||||
Router()->DisplayDebugLine( lc, 5, 10000 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ class PNS_ROUTER_BASE;
|
|||
class PNS_LINE_PLACER : public PNS_ALGO_BASE
|
||||
{
|
||||
public:
|
||||
PNS_LINE_PLACER( PNS_ROUTER *aRouter );
|
||||
PNS_LINE_PLACER( PNS_ROUTER* aRouter );
|
||||
~PNS_LINE_PLACER();
|
||||
|
||||
/**
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
* (unless NULL).
|
||||
*/
|
||||
void Start ( const VECTOR2I& aP, PNS_ITEM* aStartItem );
|
||||
|
||||
|
||||
/**
|
||||
* Function Move()
|
||||
*
|
||||
|
@ -92,14 +92,14 @@ public:
|
|||
*
|
||||
* Sets the current routing layer.
|
||||
*/
|
||||
void SetLayer ( int aLayer );
|
||||
void SetLayer( int aLayer );
|
||||
|
||||
/**
|
||||
* Function SetWidth()
|
||||
*
|
||||
* Sets the current track width.
|
||||
*/
|
||||
void SetWidth ( int aWidth );
|
||||
void SetWidth( int aWidth );
|
||||
|
||||
/**
|
||||
* Function Head()
|
||||
|
@ -167,7 +167,7 @@ public:
|
|||
*
|
||||
* Returns the most recent world state.
|
||||
*/
|
||||
PNS_NODE* CurrentNode(bool aLoopsRemoved = false) const;
|
||||
PNS_NODE* CurrentNode( bool aLoopsRemoved = false ) const;
|
||||
|
||||
/**
|
||||
* Function FlipPosture()
|
||||
|
@ -185,7 +185,6 @@ public:
|
|||
*/
|
||||
void UpdateSizes( const PNS_ROUTING_SETTINGS& aSettings );
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function route()
|
||||
|
@ -197,7 +196,6 @@ private:
|
|||
* @param aP ending point of current route.
|
||||
* @return true, if the routing is complete.
|
||||
*/
|
||||
|
||||
bool route( const VECTOR2I& aP );
|
||||
|
||||
/**
|
||||
|
@ -214,7 +212,7 @@ private:
|
|||
*
|
||||
* Sets the board to route.
|
||||
*/
|
||||
void setWorld ( PNS_NODE *aWorld );
|
||||
void setWorld ( PNS_NODE* aWorld );
|
||||
|
||||
/**
|
||||
* Function startPlacement()
|
||||
|
@ -268,9 +266,9 @@ private:
|
|||
*
|
||||
* Helper function, checking if segments a and b form an obtuse angle
|
||||
* (in 45-degree regime).
|
||||
* @return true, if angle (a, b) is obtuse
|
||||
* @return true, if angle (aA, aB) is obtuse
|
||||
*/
|
||||
bool checkObtusity( const SEG& a, const SEG& b ) const;
|
||||
bool checkObtusity( const SEG& aA, const SEG& aB ) const;
|
||||
|
||||
/**
|
||||
* Function handleSelfIntersections()
|
||||
|
@ -339,16 +337,15 @@ private:
|
|||
*/
|
||||
void routeStep( const VECTOR2I& aP );
|
||||
|
||||
///< route step, walkaround mode
|
||||
///> route step, walkaround mode
|
||||
bool rhWalkOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead);
|
||||
|
||||
///< route step, shove mode
|
||||
///> route step, shove mode
|
||||
bool rhShoveOnly ( const VECTOR2I& aP, PNS_LINE& aNewHead);
|
||||
|
||||
///< route step, mark obstacles mode
|
||||
///> route step, mark obstacles mode
|
||||
bool rhMarkObstacles ( const VECTOR2I& aP, PNS_LINE& aNewHead );
|
||||
|
||||
|
||||
///> current routing direction
|
||||
DIRECTION_45 m_direction;
|
||||
|
||||
|
@ -399,7 +396,6 @@ private:
|
|||
PNS_LINE m_currentTrace;
|
||||
|
||||
PNS_MODE m_currentMode;
|
||||
|
||||
};
|
||||
|
||||
#endif // __PNS_LINE_PLACER_H
|
||||
|
|
|
@ -38,136 +38,153 @@ PNS_LOGGER::PNS_LOGGER( )
|
|||
|
||||
PNS_LOGGER::~PNS_LOGGER()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PNS_LOGGER::Clear()
|
||||
{
|
||||
m_theLog.str(std::string());
|
||||
m_theLog.str( std::string() );
|
||||
m_groupOpened = false;
|
||||
}
|
||||
|
||||
void PNS_LOGGER::NewGroup ( const std::string& name, int iter)
|
||||
|
||||
void PNS_LOGGER::NewGroup( const std::string& aName, int aIter )
|
||||
{
|
||||
if(m_groupOpened)
|
||||
if( m_groupOpened )
|
||||
m_theLog << "endgroup" << std::endl;
|
||||
m_theLog << "group " << name << " " << iter << std::endl;
|
||||
|
||||
m_theLog << "group " << aName << " " << aIter << std::endl;
|
||||
m_groupOpened = true;
|
||||
}
|
||||
|
||||
|
||||
void PNS_LOGGER::EndGroup()
|
||||
{
|
||||
if(!m_groupOpened)
|
||||
if( !m_groupOpened )
|
||||
return;
|
||||
|
||||
m_groupOpened = false;
|
||||
m_theLog << "endgroup" << std::endl;
|
||||
}
|
||||
|
||||
void PNS_LOGGER::Log ( const PNS_ITEM *item, int kind, const std::string name )
|
||||
{
|
||||
m_theLog << "item " << kind << " " << name << " ";
|
||||
m_theLog << item->Net() << " " << item->Layers().Start() << " " << item->Layers().End() << " " << item->Marker() << " " << item->Rank();
|
||||
|
||||
switch(item->Kind())
|
||||
void PNS_LOGGER::Log ( const PNS_ITEM* aItem, int aKind, const std::string aName )
|
||||
{
|
||||
m_theLog << "aItem " << aKind << " " << aName << " ";
|
||||
m_theLog << aItem->Net() << " " << aItem->Layers().Start() << " " <<
|
||||
aItem->Layers().End() << " " << aItem->Marker() << " " << aItem->Rank();
|
||||
|
||||
switch( aItem->Kind() )
|
||||
{
|
||||
case PNS_ITEM::LINE:
|
||||
{
|
||||
PNS_LINE *l = (PNS_LINE *) item;
|
||||
PNS_LINE* l = (PNS_LINE*) aItem;
|
||||
m_theLog << " line ";
|
||||
m_theLog << l->Width() << " " << (l->EndsWithVia() ? 1 : 0) << " ";
|
||||
m_theLog << l->Width() << " " << ( l->EndsWithVia() ? 1 : 0 ) << " ";
|
||||
dumpShape ( l->Shape() );
|
||||
m_theLog << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
{
|
||||
m_theLog << " via 0 0 ";
|
||||
dumpShape ( item->Shape() );
|
||||
dumpShape ( aItem->Shape() );
|
||||
m_theLog << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
PNS_SEGMENT *s =(PNS_SEGMENT *) item;
|
||||
PNS_SEGMENT* s =(PNS_SEGMENT*) aItem;
|
||||
m_theLog << " line ";
|
||||
m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " <<s->Seg().A.y << " " << s->Seg().B.x << " " <<s->Seg().B.y << std::endl;
|
||||
m_theLog << s->Width() << " 0 linechain 2 0 " << s->Seg().A.x << " " <<
|
||||
s->Seg().A.y << " " << s->Seg().B.x << " " <<s->Seg().B.y << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::SOLID:
|
||||
{
|
||||
PNS_SOLID *s = (PNS_SOLID*) item;
|
||||
PNS_SOLID* s = (PNS_SOLID*) aItem;
|
||||
m_theLog << " solid 0 0 ";
|
||||
dumpShape ( s->Shape() );
|
||||
dumpShape( s->Shape() );
|
||||
m_theLog << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PNS_LOGGER::Log ( const SHAPE_LINE_CHAIN *l, int kind, const std::string name )
|
||||
|
||||
void PNS_LOGGER::Log( const SHAPE_LINE_CHAIN *aL, int aKind, const std::string aName )
|
||||
{
|
||||
m_theLog << "item " << kind << " " << name << " ";
|
||||
m_theLog << "item " << aKind << " " << aName << " ";
|
||||
m_theLog << 0 << " " << 0 << " " << 0 << " " << 0 << " " << 0;
|
||||
m_theLog << " line ";
|
||||
m_theLog << 0 << " " << 0 << " ";
|
||||
dumpShape ( l );
|
||||
dumpShape( aL );
|
||||
m_theLog << std::endl;
|
||||
}
|
||||
|
||||
void PNS_LOGGER::Log ( const VECTOR2I& start, const VECTOR2I& end, int kind , const std::string name)
|
||||
{
|
||||
|
||||
void PNS_LOGGER::Log( const VECTOR2I& aStart, const VECTOR2I& aEnd,
|
||||
int aKind, const std::string aName)
|
||||
{
|
||||
}
|
||||
|
||||
void PNS_LOGGER::dumpShape ( const SHAPE * sh )
|
||||
|
||||
void PNS_LOGGER::dumpShape( const SHAPE* aSh )
|
||||
{
|
||||
switch(sh->Type())
|
||||
switch( aSh->Type() )
|
||||
{
|
||||
case SH_LINE_CHAIN:
|
||||
{
|
||||
const SHAPE_LINE_CHAIN *lc = (const SHAPE_LINE_CHAIN *) sh;
|
||||
m_theLog << "linechain " << lc->PointCount() << " " << (lc->IsClosed() ? 1 : 0) << " ";
|
||||
for(int i = 0; i < lc->PointCount(); i++)
|
||||
m_theLog << lc->CPoint(i).x << " " << lc->CPoint(i).y << " ";
|
||||
const SHAPE_LINE_CHAIN* lc = (const SHAPE_LINE_CHAIN*) aSh;
|
||||
m_theLog << "linechain " << lc->PointCount() << " " << ( lc->IsClosed() ? 1 : 0 ) << " ";
|
||||
|
||||
for( int i = 0; i < lc->PointCount(); i++ )
|
||||
m_theLog << lc->CPoint( i ).x << " " << lc->CPoint( i ).y << " ";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SH_CIRCLE:
|
||||
{
|
||||
const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) sh;
|
||||
const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE*) aSh;
|
||||
m_theLog << "circle " << c->GetCenter().x << " " << c->GetCenter().y << " " << c->GetRadius();
|
||||
break;
|
||||
}
|
||||
|
||||
case SH_RECT:
|
||||
{
|
||||
const SHAPE_RECT *r = (const SHAPE_RECT *) sh;
|
||||
m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " << r->GetSize().x << " " <<r->GetSize().y;
|
||||
const SHAPE_RECT* r = (const SHAPE_RECT*) aSh;
|
||||
m_theLog << "rect " << r->GetPosition().x << " " << r->GetPosition().y << " " <<
|
||||
r->GetSize().x << " " <<r->GetSize().y;
|
||||
break;
|
||||
}
|
||||
|
||||
case SH_SEGMENT:
|
||||
{
|
||||
const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) sh;
|
||||
m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " << s->GetSeg().B.x << " " << s->GetSeg().B.y;
|
||||
const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) aSh;
|
||||
m_theLog << "linechain 2 0 " << s->GetSeg().A.x << " " << s->GetSeg().A.y << " " <<
|
||||
s->GetSeg().B.x << " " << s->GetSeg().B.y;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PNS_LOGGER::Save ( const std::string& filename )
|
||||
void PNS_LOGGER::Save( const std::string& aFilename )
|
||||
{
|
||||
|
||||
EndGroup();
|
||||
|
||||
FILE *f=fopen(filename.c_str(),"wb");
|
||||
printf("Saving to '%s' [%p]\n", filename.c_str(), f);
|
||||
FILE* f = fopen( aFilename.c_str(), "wb" );
|
||||
printf( "Saving to '%s' [%p]\n", aFilename.c_str(), f );
|
||||
const std::string s = m_theLog.str();
|
||||
fwrite(s.c_str(), 1, s.length(), f);
|
||||
fclose(f);
|
||||
fwrite( s.c_str(), 1, s.length(), f );
|
||||
fclose( f );
|
||||
}
|
||||
|
|
|
@ -32,24 +32,25 @@ class PNS_ITEM;
|
|||
class SHAPE_LINE_CHAIN;
|
||||
class SHAPE;
|
||||
|
||||
class PNS_LOGGER {
|
||||
|
||||
class PNS_LOGGER
|
||||
{
|
||||
public:
|
||||
PNS_LOGGER();
|
||||
~PNS_LOGGER();
|
||||
|
||||
void Save ( const std::string& filename );
|
||||
|
||||
void Save( const std::string& aFilename );
|
||||
void Clear();
|
||||
void NewGroup ( const std::string& name, int iter = 0);
|
||||
|
||||
void NewGroup( const std::string& aName, int aIter = 0 );
|
||||
void EndGroup();
|
||||
void Log ( const PNS_ITEM *item, int kind = 0, const std::string name = std::string () );
|
||||
void Log ( const SHAPE_LINE_CHAIN *l, int kind = 0, const std::string name = std::string () );
|
||||
void Log ( const VECTOR2I& start, const VECTOR2I& end, int kind = 0, const std::string name = std::string () );
|
||||
|
||||
void Log( const PNS_ITEM* aItem, int aKind = 0, const std::string aName = std::string() );
|
||||
void Log( const SHAPE_LINE_CHAIN *aL, int aKind = 0, const std::string aName = std::string() );
|
||||
void Log( const VECTOR2I& aStart, const VECTOR2I& aEnd, int aKind = 0,
|
||||
const std::string aName = std::string() );
|
||||
|
||||
private:
|
||||
|
||||
void dumpShape ( const SHAPE* sh );
|
||||
void dumpShape ( const SHAPE* aSh );
|
||||
|
||||
bool m_groupOpened;
|
||||
std::stringstream m_theLog;
|
||||
|
|
|
@ -53,11 +53,13 @@ PNS_NODE::PNS_NODE()
|
|||
m_parent = NULL;
|
||||
m_maxClearance = 800000; // fixme: depends on how thick traces are.
|
||||
m_index = new PNS_INDEX;
|
||||
|
||||
#ifdef DEBUG
|
||||
allocNodes.insert( this );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE::~PNS_NODE()
|
||||
{
|
||||
TRACE( 0, "PNS_NODE::delete %p", this );
|
||||
|
@ -69,7 +71,6 @@ PNS_NODE::~PNS_NODE()
|
|||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
if( allocNodes.find( this ) == allocNodes.end() )
|
||||
{
|
||||
TRACEn( 0, "attempting to free an already-free'd node.\n" );
|
||||
|
@ -77,31 +78,31 @@ PNS_NODE::~PNS_NODE()
|
|||
}
|
||||
|
||||
allocNodes.erase( this );
|
||||
|
||||
#endif
|
||||
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin();
|
||||
i != m_index->end(); ++i )
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
{
|
||||
if( (*i)->BelongsTo( this ) )
|
||||
delete *i;
|
||||
}
|
||||
|
||||
unlinkParent();
|
||||
delete m_index;
|
||||
}
|
||||
|
||||
|
||||
int PNS_NODE::GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const
|
||||
int PNS_NODE::GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const
|
||||
{
|
||||
return (*m_clearanceFunctor)( a, b );
|
||||
return (*m_clearanceFunctor)( aA, aB );
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE* PNS_NODE::Branch()
|
||||
{
|
||||
PNS_NODE* child = new PNS_NODE;
|
||||
|
||||
TRACE( 0, "PNS_NODE::branch %p (parent %p)", child % this );
|
||||
|
||||
|
||||
m_children.push_back( child );
|
||||
|
||||
child->m_depth = m_depth + 1;
|
||||
|
@ -114,10 +115,9 @@ PNS_NODE* PNS_NODE::Branch()
|
|||
// to stored items.
|
||||
if( !isRoot() )
|
||||
{
|
||||
JointMap::iterator j;
|
||||
JOINT_MAP::iterator j;
|
||||
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin();
|
||||
i != m_index->end(); ++i )
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
child->m_index->Add( *i );
|
||||
|
||||
child->m_joints = m_joints;
|
||||
|
@ -150,7 +150,7 @@ void PNS_NODE::unlinkParent()
|
|||
|
||||
// function object that visits potential obstacles and performs
|
||||
// the actual collision refining
|
||||
struct PNS_NODE::obstacleVisitor
|
||||
struct PNS_NODE::OBSTACLE_VISITOR
|
||||
{
|
||||
///> node we are searching in (either root or a branch)
|
||||
PNS_NODE* m_node;
|
||||
|
@ -159,7 +159,7 @@ struct PNS_NODE::obstacleVisitor
|
|||
PNS_NODE* m_override;
|
||||
|
||||
///> list of encountered obstacles
|
||||
Obstacles& m_tab;
|
||||
OBSTACLES& m_tab;
|
||||
|
||||
///> the item we are looking for collisions with
|
||||
const PNS_ITEM* m_item;
|
||||
|
@ -176,8 +176,7 @@ struct PNS_NODE::obstacleVisitor
|
|||
///> additional clearance
|
||||
int m_extraClearance;
|
||||
|
||||
obstacleVisitor( PNS_NODE::Obstacles& aTab, const PNS_ITEM* aItem,
|
||||
int aKindMask ) :
|
||||
OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask ) :
|
||||
m_tab( aTab ),
|
||||
m_item( aItem ),
|
||||
m_kindMask( aKindMask ),
|
||||
|
@ -185,9 +184,9 @@ struct PNS_NODE::obstacleVisitor
|
|||
m_matchCount( 0 ),
|
||||
m_extraClearance( 0 )
|
||||
{
|
||||
if(aItem->Kind() == PNS_ITEM::LINE)
|
||||
m_extraClearance += static_cast<const PNS_LINE *>(aItem)->Width() / 2;
|
||||
};
|
||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||
m_extraClearance += static_cast<const PNS_LINE*>( aItem )->Width() / 2;
|
||||
}
|
||||
|
||||
void SetCountLimit( int aLimit )
|
||||
{
|
||||
|
@ -212,7 +211,7 @@ struct PNS_NODE::obstacleVisitor
|
|||
|
||||
int clearance = m_extraClearance + m_node->GetClearance( aItem, m_item );
|
||||
|
||||
if(aItem->Kind() == PNS_ITEM::LINE)
|
||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||
clearance += static_cast<PNS_LINE *>(aItem)->Width() / 2;
|
||||
|
||||
if( !aItem->Collide( m_item, clearance ) )
|
||||
|
@ -220,7 +219,7 @@ struct PNS_NODE::obstacleVisitor
|
|||
|
||||
PNS_OBSTACLE obs;
|
||||
|
||||
obs.item = aItem;
|
||||
obs.m_item = aItem;
|
||||
m_tab.push_back( obs );
|
||||
|
||||
m_matchCount++;
|
||||
|
@ -234,9 +233,9 @@ struct PNS_NODE::obstacleVisitor
|
|||
|
||||
|
||||
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
||||
PNS_NODE::Obstacles& aObstacles, int aKindMask, int aLimitCount )
|
||||
PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount )
|
||||
{
|
||||
obstacleVisitor visitor( aObstacles, aItem, aKindMask );
|
||||
OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask );
|
||||
|
||||
#ifdef DEBUG
|
||||
assert( allocNodes.find( this ) != allocNodes.end() );
|
||||
|
@ -249,7 +248,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
|||
m_index->Query( aItem, m_maxClearance, visitor );
|
||||
|
||||
// if we haven't found enough items, look in the root branch as well.
|
||||
if( !isRoot() && ( visitor.m_matchCount < aLimitCount || aLimitCount < 0) )
|
||||
if( !isRoot() && ( visitor.m_matchCount < aLimitCount || aLimitCount < 0 ) )
|
||||
{
|
||||
visitor.SetWorld( m_root, this );
|
||||
m_root->m_index->Query( aItem, m_maxClearance, visitor );
|
||||
|
@ -259,9 +258,9 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
|||
}
|
||||
|
||||
|
||||
PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask )
|
||||
PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask )
|
||||
{
|
||||
Obstacles obs_list;
|
||||
OBSTACLES obs_list;
|
||||
bool found_isects = false;
|
||||
|
||||
const SHAPE_LINE_CHAIN& line = aItem->CLine();
|
||||
|
@ -281,13 +280,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin
|
|||
|
||||
// if(! QueryColliding ( aItem, obs_list, aKindMask ))
|
||||
if( !n )
|
||||
return OptObstacle();
|
||||
return OPT_OBSTACLE();
|
||||
|
||||
PNS_LINE& aLine = (PNS_LINE&) *aItem;
|
||||
|
||||
PNS_OBSTACLE nearest;
|
||||
nearest.item = NULL;
|
||||
nearest.dist_first = INT_MAX;
|
||||
nearest.m_item = NULL;
|
||||
nearest.m_distFirst = INT_MAX;
|
||||
|
||||
BOOST_FOREACH( PNS_OBSTACLE obs, obs_list )
|
||||
{
|
||||
|
@ -296,13 +295,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin
|
|||
|
||||
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> isect_list;
|
||||
|
||||
int clearance = GetClearance( obs.item, &aLine );
|
||||
int clearance = GetClearance( obs.m_item, &aLine );
|
||||
|
||||
SHAPE_LINE_CHAIN hull = obs.item->Hull( clearance, aItem->Width() );
|
||||
SHAPE_LINE_CHAIN hull = obs.m_item->Hull( clearance, aItem->Width() );
|
||||
|
||||
if( aLine.EndsWithVia() )
|
||||
{
|
||||
int clearance = GetClearance( obs.item, &aLine.Via() );
|
||||
int clearance = GetClearance( obs.m_item, &aLine.Via() );
|
||||
|
||||
SHAPE_LINE_CHAIN viaHull = aLine.Via().Hull( clearance, aItem->Width() );
|
||||
|
||||
|
@ -313,13 +312,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin
|
|||
int dist = aLine.CLine().Length() +
|
||||
( isect.p - aLine.Via().Pos() ).EuclideanNorm();
|
||||
|
||||
if( dist < nearest.dist_first )
|
||||
if( dist < nearest.m_distFirst )
|
||||
{
|
||||
found_isects = true;
|
||||
nearest.dist_first = dist;
|
||||
nearest.ip_first = isect.p;
|
||||
nearest.item = obs.item;
|
||||
nearest.hull = hull;
|
||||
nearest.m_distFirst = dist;
|
||||
nearest.m_ipFirst = isect.p;
|
||||
nearest.m_item = obs.m_item;
|
||||
nearest.m_hull = hull;
|
||||
}
|
||||
|
||||
if( dist > dist_max )
|
||||
|
@ -338,13 +337,13 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin
|
|||
{
|
||||
int dist = aLine.CLine().PathLength( isect.p );
|
||||
|
||||
if( dist < nearest.dist_first )
|
||||
if( dist < nearest.m_distFirst )
|
||||
{
|
||||
found_isects = true;
|
||||
nearest.dist_first = dist;
|
||||
nearest.ip_first = isect.p;
|
||||
nearest.item = obs.item;
|
||||
nearest.hull = hull;
|
||||
nearest.m_distFirst = dist;
|
||||
nearest.m_ipFirst = isect.p;
|
||||
nearest.m_item = obs.m_item;
|
||||
nearest.m_hull = hull;
|
||||
}
|
||||
|
||||
if( dist > dist_max )
|
||||
|
@ -354,37 +353,41 @@ PNS_NODE::OptObstacle PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKin
|
|||
}
|
||||
}
|
||||
|
||||
nearest.ip_last = ip_last;
|
||||
nearest.dist_last = dist_max;
|
||||
nearest.m_ipLast = ip_last;
|
||||
nearest.m_distLast = dist_max;
|
||||
}
|
||||
|
||||
if(!found_isects)
|
||||
nearest.item = obs_list[0].item;
|
||||
if( !found_isects )
|
||||
nearest.m_item = obs_list[0].m_item;
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEMSET& aSet, int aKindMask )
|
||||
|
||||
PNS_NODE::OPT_OBSTACLE PNS_NODE::CheckColliding( const PNS_ITEMSET& aSet, int aKindMask )
|
||||
{
|
||||
BOOST_FOREACH( const PNS_ITEM *item, aSet.CItems() )
|
||||
BOOST_FOREACH( const PNS_ITEM* item, aSet.CItems() )
|
||||
{
|
||||
OptObstacle obs = CheckColliding(item, aKindMask);
|
||||
if(obs)
|
||||
OPT_OBSTACLE obs = CheckColliding( item, aKindMask );
|
||||
|
||||
if( obs )
|
||||
return obs;
|
||||
}
|
||||
return OptObstacle();
|
||||
|
||||
return OPT_OBSTACLE();
|
||||
}
|
||||
|
||||
PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask )
|
||||
|
||||
PNS_NODE::OPT_OBSTACLE PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKindMask )
|
||||
{
|
||||
Obstacles obs;
|
||||
OBSTACLES obs;
|
||||
|
||||
obs.reserve( 100 );
|
||||
|
||||
if( aItemA->Kind() == PNS_ITEM::LINE )
|
||||
{
|
||||
int n = 0;
|
||||
const PNS_LINE* line = static_cast<const PNS_LINE*>(aItemA);
|
||||
const PNS_LINE* line = static_cast<const PNS_LINE*>( aItemA );
|
||||
const SHAPE_LINE_CHAIN& l = line->CLine();
|
||||
|
||||
for( int i = 0; i < l.SegmentCount(); i++ )
|
||||
|
@ -393,7 +396,7 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin
|
|||
n += QueryColliding( &s, obs, aKindMask, 1 );
|
||||
|
||||
if( n )
|
||||
return OptObstacle( obs[0] );
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
}
|
||||
|
||||
if( line->EndsWithVia() )
|
||||
|
@ -401,13 +404,13 @@ PNS_NODE::OptObstacle PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, int aKin
|
|||
n += QueryColliding( &line->Via(), obs, aKindMask, 1 );
|
||||
|
||||
if( n )
|
||||
return OptObstacle( obs[0] );
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
}
|
||||
}
|
||||
else if( QueryColliding( aItemA, obs, aKindMask, 1 ) > 0 )
|
||||
return OptObstacle( obs[0] );
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
|
||||
return OptObstacle();
|
||||
return OPT_OBSTACLE();
|
||||
}
|
||||
|
||||
|
||||
|
@ -417,23 +420,24 @@ bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, i
|
|||
int clearance = GetClearance( aItemA, aItemB );
|
||||
|
||||
// fixme: refactor
|
||||
if(aItemA->Kind() == PNS_ITEM::LINE)
|
||||
clearance += static_cast<const PNS_LINE *>(aItemA)->Width() / 2;
|
||||
if(aItemB->Kind() == PNS_ITEM::LINE)
|
||||
clearance += static_cast<const PNS_LINE *>(aItemB)->Width() / 2;
|
||||
if( aItemA->Kind() == PNS_ITEM::LINE )
|
||||
clearance += static_cast<const PNS_LINE*>( aItemA )->Width() / 2;
|
||||
if( aItemB->Kind() == PNS_ITEM::LINE )
|
||||
clearance += static_cast<const PNS_LINE*>( aItemB )->Width() / 2;
|
||||
|
||||
return aItemA->Collide( aItemB, clearance );
|
||||
}
|
||||
|
||||
|
||||
struct hitVisitor
|
||||
struct HIT_VISITOR
|
||||
{
|
||||
PNS_ITEMSET& m_items;
|
||||
const VECTOR2I& m_point;
|
||||
const PNS_NODE* m_world;
|
||||
|
||||
hitVisitor( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) :
|
||||
m_items( aTab ), m_point( aPoint ), m_world( aWorld ) {};
|
||||
HIT_VISITOR( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) :
|
||||
m_items( aTab ), m_point( aPoint ), m_world( aWorld )
|
||||
{}
|
||||
|
||||
bool operator()( PNS_ITEM* aItem )
|
||||
{
|
||||
|
@ -455,17 +459,17 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const
|
|||
|
||||
// fixme: we treat a point as an infinitely small circle - this is inefficient.
|
||||
SHAPE_CIRCLE s( aPoint, 0 );
|
||||
hitVisitor visitor( items, aPoint, this );
|
||||
HIT_VISITOR visitor( items, aPoint, this );
|
||||
|
||||
m_index->Query( &s, m_maxClearance, visitor );
|
||||
|
||||
if( !isRoot() ) // fixme: could be made cleaner
|
||||
{
|
||||
PNS_ITEMSET items_root;
|
||||
hitVisitor visitor_root( items_root, aPoint, m_root );
|
||||
HIT_VISITOR visitor_root( items_root, aPoint, m_root );
|
||||
m_root->m_index->Query( &s, m_maxClearance, visitor_root );
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, items_root.Items() )
|
||||
BOOST_FOREACH( PNS_ITEM* item, items_root.Items() )
|
||||
{
|
||||
if( !overrides( item ) )
|
||||
items.Add( item );
|
||||
|
@ -506,10 +510,10 @@ void PNS_NODE::addLine( PNS_LINE* aLine, bool aAllowRedundant )
|
|||
if ( !aAllowRedundant )
|
||||
psegR = findRedundantSegment( pseg );
|
||||
|
||||
if(psegR)
|
||||
aLine->LinkSegment(psegR);
|
||||
else {
|
||||
|
||||
if( psegR )
|
||||
aLine->LinkSegment( psegR );
|
||||
else
|
||||
{
|
||||
pseg->SetOwner( this );
|
||||
|
||||
linkJoint( s.A, pseg->Layers(), aLine->Net(), pseg );
|
||||
|
@ -532,7 +536,7 @@ void PNS_NODE::addSegment( PNS_SEGMENT* aSeg, bool aAllowRedundant )
|
|||
return;
|
||||
}
|
||||
|
||||
if ( !aAllowRedundant && findRedundantSegment ( aSeg ) )
|
||||
if( !aAllowRedundant && findRedundantSegment ( aSeg ) )
|
||||
return;
|
||||
|
||||
aSeg->SetOwner( this );
|
||||
|
@ -559,11 +563,11 @@ void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant )
|
|||
break;
|
||||
|
||||
case PNS_ITEM::LINE:
|
||||
addLine( static_cast<PNS_LINE*> (aItem), aAllowRedundant );
|
||||
addLine( static_cast<PNS_LINE*>( aItem ), aAllowRedundant );
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
addVia( static_cast<PNS_VIA*>(aItem) );
|
||||
addVia( static_cast<PNS_VIA*>( aItem ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -574,7 +578,6 @@ void PNS_NODE::Add( PNS_ITEM* aItem, bool aAllowRedundant )
|
|||
|
||||
void PNS_NODE::doRemove( PNS_ITEM* aItem )
|
||||
{
|
||||
|
||||
// assert(m_root->m_index->Contains(aItem) || m_index->Contains(aItem));
|
||||
|
||||
// case 1: removing an item that is stored in the root node from any branch:
|
||||
|
@ -612,7 +615,7 @@ void PNS_NODE::removeLine( PNS_LINE* aLine )
|
|||
assert (segRefs != NULL);
|
||||
assert (aLine->Owner());
|
||||
|
||||
if ( (int)segRefs->size() != aLine->SegmentCount())
|
||||
if ( (int) segRefs->size() != aLine->SegmentCount() )
|
||||
{
|
||||
//printf("******weird deletion: segrefs %d segcount %d hasloops %d\n", segRefs->size(), aLine->SegmentCount(), aLine->HasLoops());
|
||||
}
|
||||
|
@ -627,20 +630,19 @@ void PNS_NODE::removeLine( PNS_LINE* aLine )
|
|||
}
|
||||
|
||||
|
||||
|
||||
void PNS_NODE::removeVia( PNS_VIA* aVia )
|
||||
{
|
||||
// We have to split a single joint (associated with a via, binding together multiple layers)
|
||||
// into multiple independent joints. As I'm a lazy bastard, I simply delete the via and all its links and re-insert them.
|
||||
|
||||
PNS_JOINT::HashTag tag;
|
||||
PNS_JOINT::HASH_TAG tag;
|
||||
|
||||
VECTOR2I p ( aVia->Pos() );
|
||||
PNS_LAYERSET vLayers ( aVia->Layers() );
|
||||
VECTOR2I p( aVia->Pos() );
|
||||
PNS_LAYERSET vLayers( aVia->Layers() );
|
||||
int net = aVia->Net();
|
||||
|
||||
PNS_JOINT *jt = FindJoint( p, vLayers.Start(), net );
|
||||
PNS_JOINT::LinkedItems links ( jt->LinkList() );
|
||||
PNS_JOINT* jt = FindJoint( p, vLayers.Start(), net );
|
||||
PNS_JOINT::LINKED_ITEMS links( jt->LinkList() );
|
||||
|
||||
tag.net = net;
|
||||
tag.pos = p;
|
||||
|
@ -648,15 +650,15 @@ void PNS_NODE::removeVia( PNS_VIA* aVia )
|
|||
bool split;
|
||||
do
|
||||
{
|
||||
split = false;
|
||||
std::pair<JointMap::iterator, JointMap::iterator> range = m_joints.equal_range( tag );
|
||||
split = false;
|
||||
std::pair<JOINT_MAP::iterator, JOINT_MAP::iterator> range = m_joints.equal_range( tag );
|
||||
|
||||
if( range.first == m_joints.end() )
|
||||
break;
|
||||
|
||||
// find and remove all joints containing the via to be removed
|
||||
|
||||
for( JointMap::iterator f = range.first; f != range.second; ++f )
|
||||
for( JOINT_MAP::iterator f = range.first; f != range.second; ++f )
|
||||
{
|
||||
if( aVia->LayersOverlap ( &f->second ) )
|
||||
{
|
||||
|
@ -665,10 +667,10 @@ void PNS_NODE::removeVia( PNS_VIA* aVia )
|
|||
break;
|
||||
}
|
||||
}
|
||||
} while (split);
|
||||
} while( split );
|
||||
|
||||
// and re-link them, using the former via's link list
|
||||
BOOST_FOREACH(PNS_ITEM *item, links)
|
||||
BOOST_FOREACH(PNS_ITEM* item, links)
|
||||
{
|
||||
if( item != aVia )
|
||||
linkJoint ( p, item->Layers(), net, item );
|
||||
|
@ -677,6 +679,7 @@ void PNS_NODE::removeVia( PNS_VIA* aVia )
|
|||
doRemove( aVia );
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem )
|
||||
{
|
||||
Remove( aOldItem );
|
||||
|
@ -711,37 +714,37 @@ void PNS_NODE::Remove( PNS_ITEM* aItem )
|
|||
}
|
||||
|
||||
|
||||
void PNS_NODE::followLine( PNS_SEGMENT* current, bool scanDirection, int& pos,
|
||||
int limit, VECTOR2I* corners, PNS_SEGMENT** segments )
|
||||
void PNS_NODE::followLine( PNS_SEGMENT* aCurrent, bool aScanDirection, int& aPos,
|
||||
int aLimit, VECTOR2I* aCorners, PNS_SEGMENT** aSegments )
|
||||
{
|
||||
bool prevReversed = false;
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
const VECTOR2I p =
|
||||
(scanDirection ^ prevReversed) ? current->Seg().B : current->Seg().A;
|
||||
const PNS_JOINT *jt = FindJoint( p, current );
|
||||
( aScanDirection ^ prevReversed ) ? aCurrent->Seg().B : aCurrent->Seg().A;
|
||||
const PNS_JOINT* jt = FindJoint( p, aCurrent );
|
||||
|
||||
assert( jt );
|
||||
assert( pos > 0 && pos < limit );
|
||||
assert( aPos > 0 && aPos < aLimit );
|
||||
|
||||
corners[pos] = jt->Pos();
|
||||
segments[pos] = current;
|
||||
aCorners[aPos] = jt->Pos();
|
||||
aSegments[aPos] = aCurrent;
|
||||
|
||||
pos += (scanDirection ? 1 : -1);
|
||||
aPos += ( aScanDirection ? 1 : -1 );
|
||||
|
||||
if( !jt->IsLineCorner() )
|
||||
break;
|
||||
|
||||
current = jt->NextSegment( current );
|
||||
aCurrent = jt->NextSegment( aCurrent );
|
||||
|
||||
prevReversed =
|
||||
( jt->Pos() == (scanDirection ? current->Seg().B : current->Seg().A ) );
|
||||
( jt->Pos() == (aScanDirection ? aCurrent->Seg().B : aCurrent->Seg().A ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex)
|
||||
PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int* aOriginSegmentIndex)
|
||||
{
|
||||
const int MaxVerts = 1024;
|
||||
|
||||
|
@ -761,7 +764,7 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex)
|
|||
|
||||
int n = 0;
|
||||
|
||||
PNS_SEGMENT *prev_seg = NULL;
|
||||
PNS_SEGMENT* prev_seg = NULL;
|
||||
|
||||
for( int i = i_start + 1; i < i_end; i++ )
|
||||
{
|
||||
|
@ -773,8 +776,9 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex)
|
|||
{
|
||||
pl->LinkSegment( segs[i] );
|
||||
|
||||
if(segs[i] == aSeg && aOriginSegmentIndex)
|
||||
if( segs[i] == aSeg && aOriginSegmentIndex )
|
||||
*aOriginSegmentIndex = n;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
|
@ -782,53 +786,57 @@ PNS_LINE* PNS_NODE::AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex)
|
|||
}
|
||||
|
||||
|
||||
assert (pl->SegmentCount() != 0);
|
||||
assert (pl->SegmentCount() == (int) pl->LinkedSegments()->size());
|
||||
assert( pl->SegmentCount() != 0 );
|
||||
assert( pl->SegmentCount() == (int) pl->LinkedSegments()->size() );
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b )
|
||||
void PNS_NODE::FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB )
|
||||
{
|
||||
a = *FindJoint( aLine->CPoint( 0 ), aLine );
|
||||
b = *FindJoint( aLine->CPoint( -1 ), aLine );
|
||||
aA = *FindJoint( aLine->CPoint( 0 ), aLine );
|
||||
aB = *FindJoint( aLine->CPoint( -1 ), aLine );
|
||||
}
|
||||
|
||||
void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector<PNS_JOINT*> & aFoundJoints )
|
||||
|
||||
void PNS_NODE::MapConnectivity ( PNS_JOINT* aStart, std::vector<PNS_JOINT*>& aFoundJoints )
|
||||
{
|
||||
std::deque<PNS_JOINT*> searchQueue;
|
||||
std::set<PNS_JOINT*> processed;
|
||||
|
||||
searchQueue.push_back(aStart);
|
||||
processed.insert ( aStart );
|
||||
searchQueue.push_back( aStart );
|
||||
processed.insert( aStart );
|
||||
|
||||
while(!searchQueue.empty())
|
||||
while( !searchQueue.empty() )
|
||||
{
|
||||
PNS_JOINT *current = searchQueue.front();
|
||||
PNS_JOINT* current = searchQueue.front();
|
||||
searchQueue.pop_front();
|
||||
|
||||
BOOST_FOREACH ( PNS_ITEM *item, current->LinkList() )
|
||||
BOOST_FOREACH( PNS_ITEM* item, current->LinkList() )
|
||||
{
|
||||
if ( item->OfKind( PNS_ITEM::SEGMENT ) )
|
||||
{
|
||||
PNS_SEGMENT *seg = static_cast<PNS_SEGMENT *>(item);
|
||||
PNS_JOINT *a = FindJoint( seg->Seg().A, seg );
|
||||
PNS_JOINT *b = FindJoint( seg->Seg().B, seg );
|
||||
PNS_JOINT *next = (*a == *current) ? b : a;
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT *>( item );
|
||||
PNS_JOINT* a = FindJoint( seg->Seg().A, seg );
|
||||
PNS_JOINT* b = FindJoint( seg->Seg().B, seg );
|
||||
PNS_JOINT* next = ( *a == *current ) ? b : a;
|
||||
|
||||
if( processed.find( next ) == processed.end() )
|
||||
{
|
||||
processed.insert ( next );
|
||||
processed.insert( next );
|
||||
searchQueue.push_back( next );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(PNS_JOINT *jt, processed)
|
||||
BOOST_FOREACH(PNS_JOINT* jt, processed)
|
||||
aFoundJoints.push_back( jt );
|
||||
}
|
||||
|
||||
PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, int aKindMask )
|
||||
|
||||
PNS_ITEM* PNS_NODE::NearestUnconnectedItem( PNS_JOINT* aStart, int* aAnchor, int aKindMask )
|
||||
{
|
||||
std::set<PNS_ITEM*> disconnected;
|
||||
std::vector<PNS_JOINT*> joints;
|
||||
|
@ -836,32 +844,33 @@ PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, in
|
|||
AllItemsInNet( aStart->Net(), disconnected );
|
||||
MapConnectivity ( aStart, joints );
|
||||
|
||||
BOOST_FOREACH(PNS_JOINT *jt, joints)
|
||||
BOOST_FOREACH( PNS_JOINT *jt, joints )
|
||||
{
|
||||
BOOST_FOREACH (PNS_ITEM *link, jt->LinkList() )
|
||||
BOOST_FOREACH( PNS_ITEM* link, jt->LinkList() )
|
||||
{
|
||||
if(disconnected.find(link) != disconnected.end() )
|
||||
disconnected.erase(link);
|
||||
if( disconnected.find( link ) != disconnected.end() )
|
||||
disconnected.erase( link );
|
||||
}
|
||||
}
|
||||
|
||||
int best_dist = INT_MAX;
|
||||
PNS_ITEM *best = NULL;
|
||||
PNS_ITEM* best = NULL;
|
||||
|
||||
BOOST_FOREACH (PNS_ITEM *item, disconnected )
|
||||
BOOST_FOREACH( PNS_ITEM* item, disconnected )
|
||||
{
|
||||
if( item->OfKind ( aKindMask ) )
|
||||
if( item->OfKind( aKindMask ) )
|
||||
{
|
||||
for(int i = 0; i < item->AnchorCount(); i++)
|
||||
{
|
||||
VECTOR2I p = item->Anchor ( i );
|
||||
int d = (p - aStart->Pos()).EuclideanNorm();
|
||||
VECTOR2I p = item->Anchor( i );
|
||||
int d = ( p - aStart->Pos() ).EuclideanNorm();
|
||||
|
||||
if(d < best_dist)
|
||||
if( d < best_dist )
|
||||
{
|
||||
best_dist = d;
|
||||
best = item;
|
||||
if(aAnchor)
|
||||
|
||||
if( aAnchor )
|
||||
*aAnchor = i;
|
||||
}
|
||||
}
|
||||
|
@ -871,31 +880,32 @@ PNS_ITEM *PNS_NODE::NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor, in
|
|||
return best;
|
||||
}
|
||||
|
||||
int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector<PNS_LINE*>& aLines )
|
||||
|
||||
int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& aA, PNS_JOINT& aB, std::vector<PNS_LINE*>& aLines )
|
||||
{
|
||||
BOOST_FOREACH( PNS_ITEM* item, a.LinkList() )
|
||||
BOOST_FOREACH( PNS_ITEM* item, aA.LinkList() )
|
||||
{
|
||||
if( item->Kind() == PNS_ITEM::SEGMENT )
|
||||
{
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>(item);
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
|
||||
PNS_LINE* line = AssembleLine( seg );
|
||||
|
||||
PNS_JOINT j_start, j_end;
|
||||
|
||||
FindLineEnds( line, j_start, j_end );
|
||||
|
||||
int id_start = line->CLine().Find( aA.Pos() );
|
||||
int id_end = line->CLine().Find( aB.Pos() );
|
||||
|
||||
int id_start = line->CLine().Find (a.Pos());
|
||||
int id_end = line->CLine().Find (b.Pos());
|
||||
if( id_end < id_start )
|
||||
std::swap( id_end, id_start );
|
||||
|
||||
if(id_end < id_start)
|
||||
std::swap(id_end, id_start);
|
||||
|
||||
if(id_start >= 0 && id_end >= 0)
|
||||
if( id_start >= 0 && id_end >= 0 )
|
||||
{
|
||||
line->ClipVertexRange ( id_start, id_end );
|
||||
aLines.push_back( line );
|
||||
} else
|
||||
}
|
||||
else
|
||||
delete line;
|
||||
}
|
||||
}
|
||||
|
@ -906,12 +916,12 @@ int PNS_NODE::FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, std::vector<PN
|
|||
|
||||
PNS_JOINT* PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
|
||||
{
|
||||
PNS_JOINT::HashTag tag;
|
||||
PNS_JOINT::HASH_TAG tag;
|
||||
|
||||
tag.net = aNet;
|
||||
tag.pos = aPos;
|
||||
|
||||
JointMap::iterator f = m_joints.find( tag ), end = m_joints.end();
|
||||
JOINT_MAP::iterator f = m_joints.find( tag ), end = m_joints.end();
|
||||
|
||||
if( f == end && !isRoot() )
|
||||
{
|
||||
|
@ -936,15 +946,15 @@ PNS_JOINT* PNS_NODE::FindJoint( const VECTOR2I& aPos, int aLayer, int aNet )
|
|||
|
||||
PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet )
|
||||
{
|
||||
PNS_JOINT::HashTag tag;
|
||||
PNS_JOINT::HASH_TAG tag;
|
||||
|
||||
tag.pos = aPos;
|
||||
tag.net = aNet;
|
||||
|
||||
// try to find the joint in this node.
|
||||
JointMap::iterator f = m_joints.find( tag );
|
||||
JOINT_MAP::iterator f = m_joints.find( tag );
|
||||
|
||||
std::pair<JointMap::iterator, JointMap::iterator> range;
|
||||
std::pair<JOINT_MAP::iterator, JOINT_MAP::iterator> range;
|
||||
|
||||
// not found and we are not root? find in the root and copy results here.
|
||||
if( f == m_joints.end() && !isRoot() )
|
||||
|
@ -978,7 +988,8 @@ PNS_JOINT& PNS_NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLaye
|
|||
break;
|
||||
}
|
||||
}
|
||||
} while( merged );
|
||||
}
|
||||
while( merged );
|
||||
|
||||
return m_joints.insert( TagJointPair( tag, jt ) )->second;
|
||||
}
|
||||
|
@ -991,10 +1002,8 @@ void PNS_JOINT::Dump() const
|
|||
}
|
||||
|
||||
|
||||
void PNS_NODE::linkJoint( const VECTOR2I& aPos,
|
||||
const PNS_LAYERSET& aLayers,
|
||||
int aNet,
|
||||
PNS_ITEM* aWhere )
|
||||
void PNS_NODE::linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
|
||||
int aNet, PNS_ITEM* aWhere )
|
||||
{
|
||||
PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet );
|
||||
|
||||
|
@ -1003,7 +1012,7 @@ void PNS_NODE::linkJoint( const VECTOR2I& aPos,
|
|||
|
||||
|
||||
void PNS_NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
|
||||
int aNet, PNS_ITEM* aWhere )
|
||||
int aNet, PNS_ITEM* aWhere )
|
||||
{
|
||||
// fixme: remove dangling joints
|
||||
PNS_JOINT& jt = touchJoint( aPos, aLayers, aNet );
|
||||
|
@ -1021,7 +1030,7 @@ void PNS_NODE::Dump( bool aLong )
|
|||
for( i = m_items.begin(); i != m_items.end(); i++ )
|
||||
{
|
||||
if( (*i)->GetKind() == PNS_ITEM::SEGMENT )
|
||||
all_segs.insert( static_cast<PNS_SEGMENT*>(*i) );
|
||||
all_segs.insert( static_cast<PNS_SEGMENT*>( *i ) );
|
||||
}
|
||||
|
||||
if( !isRoot() )
|
||||
|
@ -1033,24 +1042,24 @@ void PNS_NODE::Dump( bool aLong )
|
|||
}
|
||||
}
|
||||
|
||||
JointMap::iterator j;
|
||||
JOINT_MAP::iterator j;
|
||||
|
||||
if( aLong )
|
||||
for( j = m_joints.begin(); j!=m_joints.end(); ++j )
|
||||
for( j = m_joints.begin(); j != m_joints.end(); ++j )
|
||||
{
|
||||
printf( "joint : %s, links : %d\n",
|
||||
j->second.GetPos().Format().c_str(), j->second.LinkCount() );
|
||||
PNS_JOINT::LinkedItems::const_iterator k;
|
||||
PNS_JOINT::LINKED_ITEMS::const_iterator k;
|
||||
|
||||
for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
|
||||
{
|
||||
const PNS_ITEM* item = *k;
|
||||
const PNS_ITEM* m_item = *k;
|
||||
|
||||
switch( item->GetKind() )
|
||||
switch( m_item->GetKind() )
|
||||
{
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
const PNS_SEGMENT* seg = static_cast<const PNS_SEGMENT*>(item);
|
||||
const PNS_SEGMENT* seg = static_cast<const PNS_SEGMENT*>( m_item );
|
||||
printf( " -> seg %s %s\n", seg->GetSeg().A.Format().c_str(),
|
||||
seg->GetSeg().B.Format().c_str() );
|
||||
break;
|
||||
|
@ -1075,7 +1084,6 @@ void PNS_NODE::Dump( bool aLong )
|
|||
if( aLong )
|
||||
printf( "Line: %s, net %d ", l->GetLine().Format().c_str(), l->GetNet() );
|
||||
|
||||
|
||||
for( std::vector<PNS_SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j )
|
||||
{
|
||||
printf( "%s ", (*j)->GetSeg().A.Format().c_str() );
|
||||
|
@ -1094,7 +1102,7 @@ void PNS_NODE::Dump( bool aLong )
|
|||
}
|
||||
|
||||
|
||||
void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded )
|
||||
void PNS_NODE::GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded )
|
||||
{
|
||||
aRemoved.reserve( m_override.size() );
|
||||
aAdded.reserve( m_index->Size() );
|
||||
|
@ -1102,10 +1110,10 @@ void PNS_NODE::GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded )
|
|||
if( isRoot() )
|
||||
return;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM * item, m_override )
|
||||
BOOST_FOREACH( PNS_ITEM* item, m_override )
|
||||
aRemoved.push_back( item );
|
||||
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i!=m_index->end(); ++i )
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
aAdded.push_back( *i );
|
||||
}
|
||||
|
||||
|
@ -1115,7 +1123,8 @@ void PNS_NODE::releaseChildren()
|
|||
// copy the kids as the PNS_NODE destructor erases the item from the parent node.
|
||||
std::vector<PNS_NODE*> kids = m_children;
|
||||
|
||||
BOOST_FOREACH( PNS_NODE * node, kids ) {
|
||||
BOOST_FOREACH( PNS_NODE * node, kids )
|
||||
{
|
||||
node->releaseChildren();
|
||||
delete node;
|
||||
}
|
||||
|
@ -1130,11 +1139,11 @@ void PNS_NODE::Commit( PNS_NODE* aNode )
|
|||
BOOST_FOREACH( PNS_ITEM * item, aNode->m_override )
|
||||
Remove( item );
|
||||
|
||||
for( PNS_INDEX::ItemSet::iterator i = aNode->m_index->begin();
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = aNode->m_index->begin();
|
||||
i != aNode->m_index->end(); ++i )
|
||||
{
|
||||
(*i)->SetRank ( -1 );
|
||||
(*i)->Unmark ();
|
||||
(*i)->SetRank( -1 );
|
||||
(*i)->Unmark();
|
||||
Add( *i );
|
||||
}
|
||||
|
||||
|
@ -1151,74 +1160,86 @@ void PNS_NODE::KillChildren()
|
|||
|
||||
void PNS_NODE::AllItemsInNet( int aNet, std::set<PNS_ITEM*>& aItems )
|
||||
{
|
||||
PNS_INDEX::NetItemsList* l_cur = m_index->GetItemsForNet( aNet );
|
||||
PNS_INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( aNet );
|
||||
|
||||
|
||||
if(l_cur)
|
||||
if( l_cur )
|
||||
{
|
||||
BOOST_FOREACH (PNS_ITEM *item, *l_cur )
|
||||
aItems.insert ( item );
|
||||
BOOST_FOREACH( PNS_ITEM*item, *l_cur )
|
||||
aItems.insert( item );
|
||||
}
|
||||
|
||||
if( !isRoot() )
|
||||
{
|
||||
PNS_INDEX::NetItemsList* l_root = m_root->m_index->GetItemsForNet( aNet );
|
||||
PNS_INDEX::NET_ITEMS_LIST* l_root = m_root->m_index->GetItemsForNet( aNet );
|
||||
|
||||
if(l_root)
|
||||
for( PNS_INDEX::NetItemsList::iterator i = l_root->begin(); i!= l_root->end(); ++i )
|
||||
if( l_root )
|
||||
for( PNS_INDEX::NET_ITEMS_LIST::iterator i = l_root->begin(); i!= l_root->end(); ++i )
|
||||
if( !overrides( *i ) )
|
||||
aItems.insert( *i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PNS_NODE::ClearRanks()
|
||||
{
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
{
|
||||
(*i)->SetRank(-1);
|
||||
(*i)->Mark(0);
|
||||
(*i)->SetRank( -1 );
|
||||
(*i)->Mark( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
int PNS_NODE::FindByMarker ( int aMarker, PNS_ITEMSET& aItems )
|
||||
|
||||
int PNS_NODE::FindByMarker( int aMarker, PNS_ITEMSET& aItems )
|
||||
{
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
if ( (*i)->Marker() & aMarker ) aItems.Add(*i);
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
{
|
||||
if( (*i)->Marker() & aMarker )
|
||||
aItems.Add( *i );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PNS_NODE::RemoveByMarker ( int aMarker )
|
||||
|
||||
int PNS_NODE::RemoveByMarker( int aMarker )
|
||||
{
|
||||
for( PNS_INDEX::ItemSet::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
if ( (*i)->Marker() & aMarker )
|
||||
{
|
||||
Remove (*i);
|
||||
}
|
||||
for( PNS_INDEX::ITEM_SET::iterator i = m_index->begin(); i != m_index->end(); ++i )
|
||||
{
|
||||
if ( (*i)->Marker() & aMarker )
|
||||
{
|
||||
Remove( *i );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PNS_SEGMENT* PNS_NODE::findRedundantSegment ( PNS_SEGMENT *aSeg )
|
||||
{
|
||||
PNS_JOINT *jtStart = FindJoint ( aSeg->Seg().A, aSeg );
|
||||
PNS_JOINT* jtStart = FindJoint ( aSeg->Seg().A, aSeg );
|
||||
|
||||
if(!jtStart)
|
||||
if( !jtStart )
|
||||
return NULL;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM *item, jtStart->LinkList() )
|
||||
if(item->OfKind(PNS_ITEM::SEGMENT))
|
||||
BOOST_FOREACH( PNS_ITEM* item, jtStart->LinkList() )
|
||||
{
|
||||
if( item->OfKind( PNS_ITEM::SEGMENT ) )
|
||||
{
|
||||
PNS_SEGMENT *seg2 = (PNS_SEGMENT *) item;
|
||||
PNS_SEGMENT* seg2 = (PNS_SEGMENT*) item;
|
||||
|
||||
const VECTOR2I a1 ( aSeg->Seg().A );
|
||||
const VECTOR2I b1 ( aSeg->Seg().B );
|
||||
const VECTOR2I a1( aSeg->Seg().A );
|
||||
const VECTOR2I b1( aSeg->Seg().B );
|
||||
|
||||
const VECTOR2I a2 ( seg2->Seg().A );
|
||||
const VECTOR2I b2 ( seg2->Seg().B );
|
||||
const VECTOR2I a2( seg2->Seg().A );
|
||||
const VECTOR2I b2( seg2->Seg().B );
|
||||
|
||||
if( seg2->Layers().Start() == aSeg->Layers().Start() &&
|
||||
((a1 == a2 && b1 == b2) || (a1 == b2 && a2 == b1)))
|
||||
( ( a1 == a2 && b1 == b2 ) || ( a1 == b2 && a2 == b1 ) ) )
|
||||
return seg2;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ class PNS_INDEX;
|
|||
class PNS_CLEARANCE_FUNC
|
||||
{
|
||||
public:
|
||||
virtual int operator()( const PNS_ITEM* a, const PNS_ITEM* b ) = 0;
|
||||
virtual int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ) = 0;
|
||||
virtual ~PNS_CLEARANCE_FUNC() {}
|
||||
};
|
||||
|
||||
|
@ -65,20 +65,20 @@ public:
|
|||
struct PNS_OBSTACLE
|
||||
{
|
||||
///> Item we search collisions with
|
||||
PNS_ITEM* head;
|
||||
PNS_ITEM* m_head;
|
||||
|
||||
///> Item found to be colliding with head
|
||||
PNS_ITEM* item;
|
||||
///> Item found to be colliding with m_head
|
||||
PNS_ITEM* m_item;
|
||||
|
||||
///> Hull of the colliding item
|
||||
SHAPE_LINE_CHAIN hull;
|
||||
///> Hull of the colliding m_item
|
||||
SHAPE_LINE_CHAIN m_hull;
|
||||
|
||||
///> First and last intersection point between the head item and the hull
|
||||
///> of the colliding item
|
||||
VECTOR2I ip_first, ip_last;
|
||||
///> of the colliding m_item
|
||||
VECTOR2I m_ipFirst, m_ipLast;
|
||||
|
||||
///> ... and the distance thereof
|
||||
int dist_first, dist_last;
|
||||
int m_distFirst, m_distLast;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -93,34 +93,33 @@ struct PNS_OBSTACLE
|
|||
* - lightweight cloning/branching (for recursive optimization and shove
|
||||
* springback)
|
||||
**/
|
||||
|
||||
class PNS_NODE
|
||||
{
|
||||
public:
|
||||
typedef boost::optional<PNS_OBSTACLE> OptObstacle;
|
||||
typedef std::vector<PNS_ITEM*> ItemVector;
|
||||
typedef std::vector<PNS_OBSTACLE> Obstacles;
|
||||
typedef boost::optional<PNS_OBSTACLE> OPT_OBSTACLE;
|
||||
typedef std::vector<PNS_ITEM*> ITEM_VECTOR;
|
||||
typedef std::vector<PNS_OBSTACLE> OBSTACLES;
|
||||
|
||||
PNS_NODE ();
|
||||
~PNS_NODE ();
|
||||
|
||||
///> 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* aA, const PNS_ITEM* aB ) const;
|
||||
|
||||
///> Returns the pre-set worst case clearance between any pair of items
|
||||
int GetMaxClearance () const
|
||||
int GetMaxClearance() const
|
||||
{
|
||||
return m_maxClearance;
|
||||
}
|
||||
|
||||
///> Sets the worst-case clerance between any pair of items
|
||||
void SetMaxClearance ( int aClearance )
|
||||
void SetMaxClearance( int aClearance )
|
||||
{
|
||||
m_maxClearance = aClearance;
|
||||
}
|
||||
|
||||
///> Assigns a clerance resolution function object
|
||||
void SetClearanceFunctor ( PNS_CLEARANCE_FUNC* aFunc )
|
||||
void SetClearanceFunctor( PNS_CLEARANCE_FUNC* aFunc )
|
||||
{
|
||||
m_clearanceFunctor = aFunc;
|
||||
}
|
||||
|
@ -147,11 +146,10 @@ public:
|
|||
* @param aLimitCount stop looking for collisions after finding this number of colliding items
|
||||
* @return number of obstacles found
|
||||
*/
|
||||
int QueryColliding ( const PNS_ITEM* aItem,
|
||||
Obstacles& aObstacles,
|
||||
int aKindMask = PNS_ITEM::ANY,
|
||||
int aLimitCount = -1 );
|
||||
|
||||
int QueryColliding( const PNS_ITEM* aItem,
|
||||
OBSTACLES& aObstacles,
|
||||
int aKindMask = PNS_ITEM::ANY,
|
||||
int aLimitCount = -1 );
|
||||
|
||||
/**
|
||||
* Function NearestObstacle()
|
||||
|
@ -162,7 +160,7 @@ public:
|
|||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
OptObstacle NearestObstacle ( const PNS_LINE* aItem,
|
||||
OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
|
||||
/**
|
||||
|
@ -174,7 +172,7 @@ public:
|
|||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
OptObstacle CheckColliding ( const PNS_ITEM* aItem,
|
||||
OPT_OBSTACLE CheckColliding( const PNS_ITEM* aItem,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
|
||||
|
||||
|
@ -187,7 +185,7 @@ public:
|
|||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
OptObstacle CheckColliding ( const PNS_ITEMSET& aSet,
|
||||
OPT_OBSTACLE CheckColliding( const PNS_ITEMSET& aSet,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
|
||||
|
||||
|
@ -200,9 +198,9 @@ public:
|
|||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
bool CheckColliding ( const PNS_ITEM* aItemA,
|
||||
const PNS_ITEM* aItemB,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
bool CheckColliding( const PNS_ITEM* aItemA,
|
||||
const PNS_ITEM* aItemB,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
|
||||
/**
|
||||
* Function HitTest()
|
||||
|
@ -211,7 +209,7 @@ public:
|
|||
* @param aPoint the point
|
||||
* @return the items
|
||||
*/
|
||||
const PNS_ITEMSET HitTest ( const VECTOR2I& aPoint ) const;
|
||||
const PNS_ITEMSET HitTest( const VECTOR2I& aPoint ) const;
|
||||
|
||||
/**
|
||||
* Function Add()
|
||||
|
@ -221,7 +219,7 @@ public:
|
|||
* @param aAllowRedundant if true, duplicate items are allowed (e.g. a segment or via
|
||||
* at the same coordinates as an existing one)
|
||||
*/
|
||||
void Add ( PNS_ITEM* aItem, bool aAllowRedundant = false );
|
||||
void Add( PNS_ITEM* aItem, bool aAllowRedundant = false );
|
||||
|
||||
/**
|
||||
* Function Remove()
|
||||
|
@ -229,7 +227,7 @@ public:
|
|||
* Just as the name says, removes an item from this branch.
|
||||
* @param aItem item to remove
|
||||
*/
|
||||
void Remove ( PNS_ITEM* aItem );
|
||||
void Remove( PNS_ITEM* aItem );
|
||||
|
||||
/**
|
||||
* Function Replace()
|
||||
|
@ -238,7 +236,7 @@ public:
|
|||
* @param aOldItem item to be removed
|
||||
* @param aNewItem item add instead
|
||||
*/
|
||||
void Replace ( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
|
||||
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem );
|
||||
|
||||
/**
|
||||
* Function Branch()
|
||||
|
@ -248,7 +246,7 @@ public:
|
|||
* any branches in use, their parents must NOT be deleted.
|
||||
* @return the new branch
|
||||
*/
|
||||
PNS_NODE* Branch ( );
|
||||
PNS_NODE* Branch();
|
||||
|
||||
/**
|
||||
* Function AssembleLine()
|
||||
|
@ -259,14 +257,10 @@ public:
|
|||
* @param aOriginSegmentIndex index of aSeg in the resulting line
|
||||
* @return the line
|
||||
*/
|
||||
|
||||
PNS_LINE* AssembleLine ( PNS_SEGMENT* aSeg,
|
||||
int *aOriginSegmentIndex = NULL );
|
||||
PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg, int *aOriginSegmentIndex = NULL );
|
||||
|
||||
///> Prints the contents and joints structure
|
||||
void Dump ( bool aLong = false );
|
||||
|
||||
|
||||
void Dump( bool aLong = false );
|
||||
|
||||
/**
|
||||
* Function GetUpdatedItems()
|
||||
|
@ -276,8 +270,7 @@ public:
|
|||
* @param aRemoved removed items
|
||||
* @param aAdded added items
|
||||
*/
|
||||
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded );
|
||||
|
||||
void GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded );
|
||||
|
||||
/**
|
||||
* Function Commit()
|
||||
|
@ -302,23 +295,24 @@ public:
|
|||
* Searches for a joint at a given position, linked to given item.
|
||||
* @return the joint, if found, otherwise empty
|
||||
*/
|
||||
PNS_JOINT* FindJoint( const VECTOR2I& aPos, PNS_ITEM *aItem )
|
||||
PNS_JOINT* FindJoint( const VECTOR2I& aPos, PNS_ITEM* aItem )
|
||||
{
|
||||
return FindJoint( aPos, aItem->Layers().Start(), aItem->Net() );
|
||||
}
|
||||
|
||||
void MapConnectivity ( PNS_JOINT* aStart, std::vector<PNS_JOINT *> & aFoundJoints );
|
||||
void MapConnectivity( PNS_JOINT* aStart, std::vector<PNS_JOINT*> & aFoundJoints );
|
||||
|
||||
PNS_ITEM *NearestUnconnectedItem ( PNS_JOINT *aStart, int *aAnchor = NULL, int aKindMask = PNS_ITEM::ANY);
|
||||
PNS_ITEM* NearestUnconnectedItem( PNS_JOINT* aStart, int *aAnchor = NULL,
|
||||
int aKindMask = PNS_ITEM::ANY);
|
||||
|
||||
|
||||
///> finds all lines between a pair of joints. Used by the loop removal procedure.
|
||||
int FindLinesBetweenJoints( PNS_JOINT& a,
|
||||
PNS_JOINT& b,
|
||||
int FindLinesBetweenJoints( PNS_JOINT& aA,
|
||||
PNS_JOINT& aB,
|
||||
std::vector<PNS_LINE*>& aLines );
|
||||
|
||||
///> finds the joints corresponding to the ends of line aLine
|
||||
void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b );
|
||||
void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& aA, PNS_JOINT& aB );
|
||||
|
||||
///> Destroys all child nodes. Applicable only to the root node.
|
||||
void KillChildren();
|
||||
|
@ -326,28 +320,27 @@ public:
|
|||
void AllItemsInNet( int aNet, std::set<PNS_ITEM*>& aItems );
|
||||
|
||||
void ClearRanks();
|
||||
|
||||
|
||||
int FindByMarker ( int aMarker, PNS_ITEMSET& aItems );
|
||||
int RemoveByMarker ( int aMarker );
|
||||
int FindByMarker( int aMarker, PNS_ITEMSET& aItems );
|
||||
int RemoveByMarker( int aMarker );
|
||||
|
||||
private:
|
||||
struct obstacleVisitor;
|
||||
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap;
|
||||
typedef JointMap::value_type TagJointPair;
|
||||
struct OBSTACLE_VISITOR;
|
||||
typedef boost::unordered_multimap<PNS_JOINT::HASH_TAG, PNS_JOINT> JOINT_MAP;
|
||||
typedef JOINT_MAP::value_type TagJointPair;
|
||||
|
||||
/// nodes are not copyable
|
||||
PNS_NODE ( const PNS_NODE& b );
|
||||
PNS_NODE& operator= ( const PNS_NODE& b );
|
||||
PNS_NODE( const PNS_NODE& aB );
|
||||
PNS_NODE& operator=( const PNS_NODE& aB );
|
||||
|
||||
///> 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
|
||||
///> touches a joint and links it to an m_item
|
||||
void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
|
||||
int aNet, PNS_ITEM* aWhere );
|
||||
int aNet, PNS_ITEM* aWhere );
|
||||
|
||||
///> unlinks an item from a joint
|
||||
void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
|
||||
|
@ -372,26 +365,26 @@ private:
|
|||
return m_parent == NULL;
|
||||
}
|
||||
|
||||
///> checks if this branch contains an updated version of the item
|
||||
///> checks if this branch contains an updated version of the m_item
|
||||
///> from the root branch.
|
||||
bool overrides( PNS_ITEM* aItem ) const
|
||||
{
|
||||
return m_override.find( aItem ) != m_override.end();
|
||||
}
|
||||
|
||||
PNS_SEGMENT *findRedundantSegment ( PNS_SEGMENT *aSeg );
|
||||
PNS_SEGMENT *findRedundantSegment ( PNS_SEGMENT* aSeg );
|
||||
|
||||
///> scans the joint map, forming a line starting from segment (current).
|
||||
void followLine ( PNS_SEGMENT* current,
|
||||
bool scanDirection,
|
||||
int& pos,
|
||||
int limit,
|
||||
VECTOR2I* corners,
|
||||
PNS_SEGMENT** segments );
|
||||
void followLine( PNS_SEGMENT* aCurrent,
|
||||
bool aScanDirection,
|
||||
int& aPos,
|
||||
int aLimit,
|
||||
VECTOR2I* aCorners,
|
||||
PNS_SEGMENT** aSegments );
|
||||
|
||||
///> hash table with the joints, linking the items. Joints are hashed by
|
||||
///> their position, layer set and net.
|
||||
JointMap m_joints;
|
||||
JOINT_MAP m_joints;
|
||||
|
||||
///> node this node was branched from
|
||||
PNS_NODE* m_parent;
|
||||
|
|
|
@ -30,14 +30,11 @@
|
|||
#include "pns_router.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* Cost Estimator Methods
|
||||
*
|
||||
*/
|
||||
|
||||
int PNS_COST_ESTIMATOR::CornerCost( const SEG& a, const SEG& b )
|
||||
int PNS_COST_ESTIMATOR::CornerCost( const SEG& aA, const SEG& aB )
|
||||
{
|
||||
DIRECTION_45 dir_a( a ), dir_b( b );
|
||||
DIRECTION_45 dir_a( aA ), dir_b( aB );
|
||||
|
||||
switch( dir_a.Angle( dir_b ) )
|
||||
{
|
||||
|
@ -109,8 +106,8 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther,
|
|||
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
|
||||
return true;
|
||||
|
||||
else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost <
|
||||
m_lengthCost * aLengthTollerance )
|
||||
else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance &&
|
||||
aOther.m_lengthCost < m_lengthCost * aLengthTollerance )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -118,9 +115,7 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther,
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
* Optimizer
|
||||
*
|
||||
**/
|
||||
PNS_OPTIMIZER::PNS_OPTIMIZER( PNS_NODE* aWorld ) :
|
||||
m_world( aWorld ), m_collisionKindMask( PNS_ITEM::ANY ), m_effortLevel( MERGE_SEGMENTS )
|
||||
|
@ -135,14 +130,14 @@ PNS_OPTIMIZER::~PNS_OPTIMIZER()
|
|||
}
|
||||
|
||||
|
||||
struct PNS_OPTIMIZER::CacheVisitor
|
||||
struct PNS_OPTIMIZER::CACHE_VISITOR
|
||||
{
|
||||
CacheVisitor( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) :
|
||||
CACHE_VISITOR( const PNS_ITEM* aOurItem, PNS_NODE* aNode, int aMask ) :
|
||||
m_ourItem( aOurItem ),
|
||||
m_collidingItem( NULL ),
|
||||
m_node( aNode ),
|
||||
m_mask( aMask )
|
||||
{};
|
||||
{}
|
||||
|
||||
bool operator()( PNS_ITEM* aOtherItem )
|
||||
{
|
||||
|
@ -171,14 +166,14 @@ void PNS_OPTIMIZER::cacheAdd( PNS_ITEM* aItem, bool aIsStatic = false )
|
|||
return;
|
||||
|
||||
m_cache.Add( aItem );
|
||||
m_cacheTags[aItem].hits = 1;
|
||||
m_cacheTags[aItem].isStatic = aIsStatic;
|
||||
m_cacheTags[aItem].m_hits = 1;
|
||||
m_cacheTags[aItem].m_isStatic = aIsStatic;
|
||||
}
|
||||
|
||||
|
||||
void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int aEndVertex )
|
||||
{
|
||||
PNS_LINE::SegmentRefs* segs = aLine->LinkedSegments();
|
||||
PNS_LINE::SEGMENT_REFS* segs = aLine->LinkedSegments();
|
||||
|
||||
if( !segs )
|
||||
return;
|
||||
|
@ -198,7 +193,7 @@ void PNS_OPTIMIZER::removeCachedSegments( PNS_LINE* aLine, int aStartVertex, int
|
|||
void PNS_OPTIMIZER::CacheRemove( PNS_ITEM* aItem )
|
||||
{
|
||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||
removeCachedSegments( static_cast<PNS_LINE*> (aItem) );
|
||||
removeCachedSegments( static_cast<PNS_LINE*>( aItem ) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -219,7 +214,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
|
|||
|
||||
for( CachedItemTags::iterator i = m_cacheTags.begin(); i!= m_cacheTags.end(); ++i )
|
||||
{
|
||||
if( i->second.isStatic )
|
||||
if( i->second.m_isStatic )
|
||||
{
|
||||
m_cache.Remove( i->first );
|
||||
m_cacheTags.erase( i->first );
|
||||
|
@ -230,7 +225,7 @@ void PNS_OPTIMIZER::ClearCache( bool aStaticOnly )
|
|||
|
||||
bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache )
|
||||
{
|
||||
CacheVisitor v( aItem, m_world, m_collisionKindMask );
|
||||
CACHE_VISITOR v( aItem, m_world, m_collisionKindMask );
|
||||
|
||||
return m_world->CheckColliding( aItem );
|
||||
|
||||
|
@ -239,19 +234,19 @@ bool PNS_OPTIMIZER::checkColliding( PNS_ITEM* aItem, bool aUpdateCache )
|
|||
|
||||
if( !v.m_collidingItem )
|
||||
{
|
||||
PNS_NODE::OptObstacle obs = m_world->CheckColliding( aItem );
|
||||
PNS_NODE::OPT_OBSTACLE obs = m_world->CheckColliding( aItem );
|
||||
|
||||
if( obs )
|
||||
{
|
||||
if( aUpdateCache )
|
||||
cacheAdd( obs->item );
|
||||
cacheAdd( obs->m_item );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cacheTags[v.m_collidingItem].hits++;
|
||||
m_cacheTags[v.m_collidingItem].m_hits++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -430,7 +425,6 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath,
|
|||
|
||||
int cost_orig = PNS_COST_ESTIMATOR::CornerCost( aCurrentPath );
|
||||
|
||||
|
||||
if( aLine->SegmentCount() < 4 )
|
||||
return false;
|
||||
|
||||
|
@ -442,7 +436,8 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath,
|
|||
const SEG s1 = aCurrentPath.CSegment( n );
|
||||
const SEG s2 = aCurrentPath.CSegment( n + step );
|
||||
|
||||
SHAPE_LINE_CHAIN path[2], * picked = NULL;
|
||||
SHAPE_LINE_CHAIN path[2];
|
||||
SHAPE_LINE_CHAIN* picked = NULL;
|
||||
int cost[2];
|
||||
|
||||
for( int i = 0; i < 2; i++ )
|
||||
|
@ -485,10 +480,10 @@ bool PNS_OPTIMIZER::mergeStep( PNS_LINE* aLine, SHAPE_LINE_CHAIN& aCurrentPath,
|
|||
}
|
||||
|
||||
|
||||
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth,
|
||||
PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::circleBreakouts( int aWidth,
|
||||
const SHAPE* aShape, bool aPermitDiagonal ) const
|
||||
{
|
||||
BreakoutList breakouts;
|
||||
BREAKOUT_LIST breakouts;
|
||||
|
||||
for( int angle = 0; angle < 360; angle += 45 )
|
||||
{
|
||||
|
@ -505,12 +500,12 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::circleBreakouts( int aWidth,
|
|||
}
|
||||
|
||||
|
||||
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
|
||||
PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::rectBreakouts( int aWidth,
|
||||
const SHAPE* aShape, bool aPermitDiagonal ) const
|
||||
{
|
||||
const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>(aShape);
|
||||
VECTOR2I s = rect->GetSize(), c = rect->GetPosition() + VECTOR2I( s.x / 2, s.y / 2 );
|
||||
BreakoutList breakouts;
|
||||
BREAKOUT_LIST breakouts;
|
||||
|
||||
VECTOR2I d_offset;
|
||||
|
||||
|
@ -520,7 +515,6 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
|
|||
VECTOR2I d_vert = VECTOR2I( 0, s.y / 2 + aWidth );
|
||||
VECTOR2I d_horiz = VECTOR2I( s.x / 2 + aWidth, 0 );
|
||||
|
||||
|
||||
breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_horiz ) );
|
||||
breakouts.push_back( SHAPE_LINE_CHAIN( c, c - d_horiz ) );
|
||||
breakouts.push_back( SHAPE_LINE_CHAIN( c, c + d_vert ) );
|
||||
|
@ -560,59 +554,59 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
|
|||
}
|
||||
|
||||
|
||||
PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth,
|
||||
PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::computeBreakouts( int aWidth,
|
||||
const PNS_ITEM* aItem, bool aPermitDiagonal ) const
|
||||
{
|
||||
switch( aItem->Kind() )
|
||||
{
|
||||
case PNS_ITEM::VIA:
|
||||
{
|
||||
const PNS_VIA* via = static_cast<const PNS_VIA*>( aItem );
|
||||
return circleBreakouts( aWidth, via->Shape(), aPermitDiagonal );
|
||||
}
|
||||
{
|
||||
const PNS_VIA* via = static_cast<const PNS_VIA*>( aItem );
|
||||
return circleBreakouts( aWidth, via->Shape(), aPermitDiagonal );
|
||||
}
|
||||
|
||||
case PNS_ITEM::SOLID:
|
||||
{
|
||||
const SHAPE* shape = aItem->Shape();
|
||||
|
||||
switch( shape->Type() )
|
||||
{
|
||||
const SHAPE* shape = aItem->Shape();
|
||||
case SH_RECT:
|
||||
return rectBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
switch( shape->Type() )
|
||||
{
|
||||
case SH_RECT:
|
||||
return rectBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
case SH_SEGMENT:
|
||||
{
|
||||
const SHAPE_SEGMENT *seg = static_cast<const SHAPE_SEGMENT*> (shape);
|
||||
const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg );
|
||||
return rectBreakouts( aWidth, &rect, aPermitDiagonal );
|
||||
}
|
||||
|
||||
case SH_CIRCLE:
|
||||
return circleBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case SH_SEGMENT:
|
||||
{
|
||||
const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*> (shape);
|
||||
const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg );
|
||||
return rectBreakouts( aWidth, &rect, aPermitDiagonal );
|
||||
}
|
||||
|
||||
case SH_CIRCLE:
|
||||
return circleBreakouts( aWidth, shape, aPermitDiagonal );
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return BreakoutList();
|
||||
return BREAKOUT_LIST();
|
||||
}
|
||||
|
||||
|
||||
PNS_ITEM* PNS_OPTIMIZER::findPadOrVia( int aLayer, int aNet, const VECTOR2I& aP ) const
|
||||
{
|
||||
PNS_JOINT *jt = m_world->FindJoint( aP, aLayer, aNet );
|
||||
PNS_JOINT* jt = m_world->FindJoint( aP, aLayer, aNet );
|
||||
|
||||
if( !jt )
|
||||
return NULL;
|
||||
|
||||
BOOST_FOREACH( PNS_ITEM* item, jt->LinkList() )
|
||||
{
|
||||
if( item->OfKind (PNS_ITEM::VIA | PNS_ITEM::SOLID ) )
|
||||
if( item->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID ) )
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -632,7 +626,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
|
|||
typedef std::pair<int, SHAPE_LINE_CHAIN> RtVariant;
|
||||
std::vector<RtVariant> variants;
|
||||
|
||||
BreakoutList breakouts = computeBreakouts( aLine->Width(), aPad, true );
|
||||
BREAKOUT_LIST breakouts = computeBreakouts( aLine->Width(), aPad, true );
|
||||
|
||||
SHAPE_LINE_CHAIN line = ( aEnd ? aLine->CLine().Reverse() : aLine->CLine() );
|
||||
|
||||
|
@ -647,7 +641,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
|
|||
{
|
||||
SHAPE_LINE_CHAIN v;
|
||||
SHAPE_LINE_CHAIN connect = dir.BuildInitialTrace( l.CPoint( -1 ),
|
||||
line.CPoint( p ), diag == 0 );
|
||||
line.CPoint( p ), diag == 0 );
|
||||
|
||||
DIRECTION_45 dir_bkout( l.CSegment( -1 ) );
|
||||
|
||||
|
@ -739,9 +733,10 @@ bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine )
|
|||
|
||||
if( endPad )
|
||||
smartPadsSingle( aLine, endPad, true,
|
||||
vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx );
|
||||
vtx < 0 ? line.PointCount() - 1 : line.PointCount() - 1 - vtx );
|
||||
|
||||
aLine->Line().Simplify();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -756,7 +751,7 @@ bool PNS_OPTIMIZER::Optimize( PNS_LINE* aLine, int aEffortLevel, PNS_NODE* aWorl
|
|||
}
|
||||
|
||||
|
||||
bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE * aLine )
|
||||
bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE* aLine )
|
||||
{
|
||||
if( aLine->PointCount() < 3 )
|
||||
return false;
|
||||
|
@ -769,40 +764,35 @@ bool PNS_OPTIMIZER::fanoutCleanup( PNS_LINE * aLine )
|
|||
int thr = aLine->Width() * 10;
|
||||
int len = aLine->CLine().Length();
|
||||
|
||||
|
||||
if(!startPad)
|
||||
if( !startPad )
|
||||
return false;
|
||||
|
||||
|
||||
bool startMatch = startPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID);
|
||||
bool startMatch = startPad->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID );
|
||||
bool endMatch = false;
|
||||
|
||||
if(endPad)
|
||||
{
|
||||
endMatch = endPad->OfKind(PNS_ITEM::VIA | PNS_ITEM::SOLID);
|
||||
endMatch = endPad->OfKind( PNS_ITEM::VIA | PNS_ITEM::SOLID );
|
||||
} else {
|
||||
endMatch = aLine->EndsWithVia();
|
||||
}
|
||||
|
||||
|
||||
if(startMatch && endMatch && len < thr)
|
||||
if( startMatch && endMatch && len < thr )
|
||||
{
|
||||
|
||||
for(int i = 0; i < 2; i++ )
|
||||
{
|
||||
SHAPE_LINE_CHAIN l2 = DIRECTION_45().BuildInitialTrace(p_start, p_end, i);
|
||||
PNS_ROUTER::GetInstance()->DisplayDebugLine (l2, 4, 10000);
|
||||
SHAPE_LINE_CHAIN l2 = DIRECTION_45().BuildInitialTrace( p_start, p_end, i );
|
||||
PNS_ROUTER::GetInstance()->DisplayDebugLine( l2, 4, 10000 );
|
||||
PNS_LINE repl;
|
||||
repl = PNS_LINE (*aLine, l2 );
|
||||
|
||||
repl = PNS_LINE( *aLine, l2 );
|
||||
|
||||
|
||||
if (!m_world->CheckColliding(&repl))
|
||||
if( !m_world->CheckColliding( &repl ) )
|
||||
{
|
||||
aLine->SetShape(repl.CLine());
|
||||
aLine->SetShape( repl.CLine() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -38,23 +38,22 @@ class PNS_ROUTER;
|
|||
*
|
||||
* Calculates the cost of a given line, taking corner angles and total length into account.
|
||||
**/
|
||||
|
||||
class PNS_COST_ESTIMATOR
|
||||
{
|
||||
public:
|
||||
PNS_COST_ESTIMATOR() :
|
||||
m_lengthCost( 0 ),
|
||||
m_cornerCost( 0 )
|
||||
{};
|
||||
{}
|
||||
|
||||
PNS_COST_ESTIMATOR( const PNS_COST_ESTIMATOR& b ) :
|
||||
m_lengthCost( b.m_lengthCost ),
|
||||
m_cornerCost( b.m_cornerCost )
|
||||
{};
|
||||
PNS_COST_ESTIMATOR( const PNS_COST_ESTIMATOR& aB ) :
|
||||
m_lengthCost( aB.m_lengthCost ),
|
||||
m_cornerCost( aB.m_cornerCost )
|
||||
{}
|
||||
|
||||
~PNS_COST_ESTIMATOR() {};
|
||||
|
||||
static int CornerCost( const SEG& a, const SEG& b );
|
||||
static int CornerCost( const SEG& aA, const SEG& aB );
|
||||
static int CornerCost( const SHAPE_LINE_CHAIN& aLine );
|
||||
static int CornerCost( const PNS_LINE& aLine );
|
||||
|
||||
|
@ -63,7 +62,7 @@ public:
|
|||
void Replace( PNS_LINE& aOldLine, PNS_LINE& aNewLine );
|
||||
|
||||
bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance,
|
||||
double aCornerTollerace ) const;
|
||||
double aCornerTollerace ) const;
|
||||
|
||||
double GetLengthCost() const { return m_lengthCost; }
|
||||
double GetCornerCost() const { return m_cornerCost; }
|
||||
|
@ -84,7 +83,6 @@ private:
|
|||
* 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).
|
||||
**/
|
||||
|
||||
class PNS_OPTIMIZER
|
||||
{
|
||||
public:
|
||||
|
@ -122,14 +120,14 @@ public:
|
|||
private:
|
||||
static const int MaxCachedItems = 256;
|
||||
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList;
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> BREAKOUT_LIST;
|
||||
|
||||
struct CacheVisitor;
|
||||
struct CACHE_VISITOR;
|
||||
|
||||
struct CachedItem
|
||||
struct CACHED_ITEM
|
||||
{
|
||||
int hits;
|
||||
bool isStatic;
|
||||
int m_hits;
|
||||
bool m_isStatic;
|
||||
};
|
||||
|
||||
bool mergeObtuse( PNS_LINE* aLine );
|
||||
|
@ -142,15 +140,13 @@ private:
|
|||
bool checkColliding( PNS_ITEM* aItem, bool aUpdateCache = true );
|
||||
bool checkColliding( PNS_LINE* aLine, const SHAPE_LINE_CHAIN& aOptPath );
|
||||
|
||||
|
||||
void cacheAdd( PNS_ITEM* aItem, bool aIsStatic );
|
||||
void removeCachedSegments( PNS_LINE* aLine, int aStartVertex = 0, int aEndVertex = -1 );
|
||||
|
||||
BreakoutList circleBreakouts( 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 computeBreakouts( int aWidth, const PNS_ITEM* aItem,
|
||||
bool aPermitDiagonal ) const;
|
||||
BREAKOUT_LIST circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
|
||||
BREAKOUT_LIST rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
|
||||
BREAKOUT_LIST ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
|
||||
BREAKOUT_LIST computeBreakouts( int aWidth, const PNS_ITEM* aItem, bool aPermitDiagonal ) const;
|
||||
|
||||
int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex );
|
||||
|
||||
|
@ -158,7 +154,7 @@ private:
|
|||
|
||||
SHAPE_INDEX_LIST<PNS_ITEM*> m_cache;
|
||||
|
||||
typedef boost::unordered_map<PNS_ITEM*, CachedItem> CachedItemTags;
|
||||
typedef boost::unordered_map<PNS_ITEM*, CACHED_ITEM> CachedItemTags;
|
||||
CachedItemTags m_cacheTags;
|
||||
PNS_NODE* m_world;
|
||||
int m_collisionKindMask;
|
||||
|
|
|
@ -82,28 +82,28 @@ public:
|
|||
m_defaultClearance = 254000; // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance();
|
||||
}
|
||||
|
||||
int localPadClearance( const PNS_ITEM * item ) const
|
||||
int localPadClearance( const PNS_ITEM* aItem ) const
|
||||
{
|
||||
if(!item->Parent() || item->Parent()->Type() != PCB_PAD_T )
|
||||
if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T )
|
||||
return 0;
|
||||
|
||||
const D_PAD *pad = static_cast<D_PAD *>( item->Parent() );
|
||||
const D_PAD* pad = static_cast<D_PAD*>( aItem->Parent() );
|
||||
|
||||
return pad->GetLocalClearance();
|
||||
}
|
||||
|
||||
int operator()( const PNS_ITEM* a, const PNS_ITEM* b )
|
||||
int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB )
|
||||
{
|
||||
int net_a = a->Net();
|
||||
int cl_a = (net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance);
|
||||
int net_b = b->Net();
|
||||
int cl_b = (net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance);
|
||||
int net_a = aA->Net();
|
||||
int cl_a = ( net_a >= 0 ? m_clearanceCache[net_a] : m_defaultClearance );
|
||||
int net_b = aB->Net();
|
||||
int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b] : m_defaultClearance );
|
||||
|
||||
int pad_a = localPadClearance( a );
|
||||
int pad_b = localPadClearance( b );
|
||||
int pad_a = localPadClearance( aA );
|
||||
int pad_b = localPadClearance( aB );
|
||||
|
||||
cl_a = std::max(cl_a, pad_a);
|
||||
cl_b = std::max(cl_b, pad_b);
|
||||
cl_a = std::max( cl_a, pad_a );
|
||||
cl_b = std::max( cl_b, pad_b );
|
||||
|
||||
return std::max( cl_a, cl_b );
|
||||
}
|
||||
|
@ -113,9 +113,10 @@ private:
|
|||
int m_defaultClearance;
|
||||
};
|
||||
|
||||
|
||||
PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
||||
{
|
||||
PNS_LAYERSET layers ( 0, 15 );
|
||||
PNS_LAYERSET layers( 0, 15 );
|
||||
|
||||
switch( aPad->GetAttribute() )
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
|||
|
||||
for( i = FIRST_COPPER_LAYER; i <= LAST_COPPER_LAYER; i++ )
|
||||
{
|
||||
if( lmsk & (1 << i) )
|
||||
if( lmsk & ( 1 << i ) )
|
||||
{
|
||||
layers = PNS_LAYERSET( i );
|
||||
break;
|
||||
|
@ -162,17 +163,16 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
|||
double orient = aPad->GetOrientation() / 10.0;
|
||||
bool nonOrtho = false;
|
||||
|
||||
|
||||
if( orient == 90.0 || orient == 270.0 )
|
||||
sz = VECTOR2I( sz.y, sz.x );
|
||||
else if( orient != 0.0 && orient != 180.0 )
|
||||
{
|
||||
// rotated pads are replaced by for the moment by circles due to my laziness ;)
|
||||
solid->SetShape ( new SHAPE_CIRCLE (c, std::min(sz.x, sz.y) / 2 ) );
|
||||
solid->SetShape( new SHAPE_CIRCLE( c, std::min( sz.x, sz.y ) / 2 ) );
|
||||
nonOrtho = true;
|
||||
}
|
||||
|
||||
if(!nonOrtho)
|
||||
if( !nonOrtho )
|
||||
{
|
||||
switch( aPad->GetShape() )
|
||||
{
|
||||
|
@ -183,15 +183,17 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
|||
case PAD_OVAL:
|
||||
if( sz.x == sz.y )
|
||||
solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
|
||||
else {
|
||||
else
|
||||
{
|
||||
VECTOR2I delta;
|
||||
|
||||
if (sz.x > sz.y)
|
||||
delta = VECTOR2I((sz.x - sz.y) / 2, 0);
|
||||
if( sz.x > sz.y )
|
||||
delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 );
|
||||
else
|
||||
delta = VECTOR2I(0, (sz.y - sz.x) / 2);
|
||||
delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 );
|
||||
|
||||
SHAPE_SEGMENT *shape = new SHAPE_SEGMENT( c - delta, c + delta, std::min(sz.x, sz.y) );
|
||||
SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta,
|
||||
std::min( sz.x, sz.y ) );
|
||||
solid->SetShape( shape );
|
||||
}
|
||||
break;
|
||||
|
@ -203,6 +205,7 @@ PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad )
|
|||
default:
|
||||
TRACEn( 0, "unsupported pad shape" );
|
||||
delete solid;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +253,8 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
|
|||
LAYER_MSK mask = m_board->GetEnabledLayers() & m_board->GetVisibleLayers();
|
||||
LAYER_NUM l = m_currentLayer;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
l += ( aUp ? 1 : -1 );
|
||||
|
||||
if( l > LAST_COPPER_LAYER )
|
||||
|
@ -261,7 +265,8 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
|
|||
|
||||
if( mask & GetLayerMask( l ) )
|
||||
return l;
|
||||
} while( l != m_currentLayer );
|
||||
}
|
||||
while( l != m_currentLayer );
|
||||
|
||||
return l;
|
||||
}
|
||||
|
@ -269,7 +274,6 @@ int PNS_ROUTER::NextCopperLayer( bool aUp )
|
|||
|
||||
void PNS_ROUTER::SyncWorld()
|
||||
{
|
||||
|
||||
if( !m_board )
|
||||
{
|
||||
TRACEn( 0, "No board attached, aborting sync." );
|
||||
|
@ -379,13 +383,6 @@ void PNS_ROUTER::ClearWorld()
|
|||
}
|
||||
|
||||
|
||||
/*void PNS_ROUTER::SetCurrentWidth( int w )
|
||||
{
|
||||
// fixme: change width while routing
|
||||
m_currentWidth = w;
|
||||
}*/
|
||||
|
||||
|
||||
bool PNS_ROUTER::RoutingInProgress() const
|
||||
{
|
||||
return m_state != IDLE;
|
||||
|
@ -405,49 +402,49 @@ const PNS_ITEMSET PNS_ROUTER::QueryHoverItems( const VECTOR2I& aP )
|
|||
}
|
||||
|
||||
|
||||
const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment )
|
||||
const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment )
|
||||
{
|
||||
VECTOR2I anchor;
|
||||
|
||||
if( !item )
|
||||
if( !aItem )
|
||||
{
|
||||
aSplitsSegment = false;
|
||||
return aP;
|
||||
}
|
||||
|
||||
switch( item->Kind() )
|
||||
switch( aItem->Kind() )
|
||||
{
|
||||
case PNS_ITEM::SOLID:
|
||||
anchor = static_cast<PNS_SOLID*>(item)->Pos();
|
||||
anchor = static_cast<PNS_SOLID*>( aItem )->Pos();
|
||||
aSplitsSegment = false;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
anchor = static_cast<PNS_VIA*>(item)->Pos();
|
||||
anchor = static_cast<PNS_VIA*>( aItem )->Pos();
|
||||
aSplitsSegment = false;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( aItem );
|
||||
const SEG& s = seg->Seg();
|
||||
int w = seg->Width();
|
||||
|
||||
aSplitsSegment = false;
|
||||
|
||||
if( ( aP - s.A ).EuclideanNorm() < w / 2 )
|
||||
anchor = s.A;
|
||||
else if( ( aP - s.B ).EuclideanNorm() < w / 2 )
|
||||
anchor = s.B;
|
||||
else
|
||||
{
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
|
||||
const SEG& s = seg->Seg();
|
||||
int w = seg->Width();
|
||||
|
||||
aSplitsSegment = false;
|
||||
|
||||
if( ( aP - s.A ).EuclideanNorm() < w / 2 )
|
||||
anchor = s.A;
|
||||
else if( ( aP - s.B ).EuclideanNorm() < w / 2 )
|
||||
anchor = s.B;
|
||||
else
|
||||
{
|
||||
anchor = s.NearestPoint( aP );
|
||||
aSplitsSegment = true;
|
||||
}
|
||||
|
||||
break;
|
||||
anchor = s.NearestPoint( aP );
|
||||
aSplitsSegment = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -455,16 +452,19 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplit
|
|||
return anchor;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
||||
{
|
||||
if(!aStartItem || aStartItem->OfKind(PNS_ITEM::SOLID))
|
||||
if( !aStartItem || aStartItem->OfKind( PNS_ITEM::SOLID ) )
|
||||
return false;
|
||||
|
||||
m_dragger = new PNS_DRAGGER ( this );
|
||||
m_dragger->SetWorld( m_world );
|
||||
|
||||
if( m_dragger->Start ( aP, aStartItem ) )
|
||||
m_state = DRAG_SEGMENT;
|
||||
else {
|
||||
else
|
||||
{
|
||||
delete m_dragger;
|
||||
m_state = IDLE;
|
||||
return false;
|
||||
|
@ -476,8 +476,6 @@ bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
|||
|
||||
bool PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem )
|
||||
{
|
||||
|
||||
|
||||
m_state = ROUTE_TRACK;
|
||||
|
||||
m_placer = new PNS_LINE_PLACER( this );
|
||||
|
@ -518,11 +516,11 @@ void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance
|
|||
{
|
||||
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems );
|
||||
|
||||
if(aColor >= 0)
|
||||
pitem->SetColor ( KIGFX::COLOR4D ( aColor ));
|
||||
if( aColor >= 0 )
|
||||
pitem->SetColor( KIGFX::COLOR4D ( aColor ) );
|
||||
|
||||
if(aClearance >= 0)
|
||||
pitem->SetClearance ( aClearance );
|
||||
if( aClearance >= 0 )
|
||||
pitem->SetClearance( aClearance );
|
||||
|
||||
m_previewItems->Add( pitem );
|
||||
|
||||
|
@ -530,12 +528,14 @@ void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance
|
|||
m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::DisplayItems( const PNS_ITEMSET& aItems )
|
||||
{
|
||||
BOOST_FOREACH(const PNS_ITEM *item, aItems.CItems())
|
||||
DisplayItem(item);
|
||||
BOOST_FOREACH( const PNS_ITEM *item, aItems.CItems() )
|
||||
DisplayItem( item );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth )
|
||||
{
|
||||
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems );
|
||||
|
@ -547,18 +547,17 @@ void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int
|
|||
}
|
||||
|
||||
|
||||
|
||||
void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I pos, int aType )
|
||||
void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I aPos, int aType )
|
||||
{
|
||||
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems );
|
||||
|
||||
pitem->Point( pos, aType );
|
||||
pitem->Point( aPos, aType );
|
||||
m_previewItems->Add( pitem );
|
||||
pitem->ViewSetVisible( true );
|
||||
m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem )
|
||||
{
|
||||
m_currentEnd = aP;
|
||||
|
@ -573,57 +572,62 @@ void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem )
|
|||
case DRAG_SEGMENT:
|
||||
moveDragging (aP, endItem );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* endItem )
|
||||
|
||||
void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
||||
{
|
||||
eraseView();
|
||||
|
||||
m_dragger->Drag( aP );
|
||||
PNS_ITEMSET dragged = m_dragger->Traces();
|
||||
|
||||
updateView ( m_dragger->CurrentNode ( ), dragged );
|
||||
updateView ( m_dragger->CurrentNode(), dragged );
|
||||
}
|
||||
|
||||
void PNS_ROUTER::markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved )
|
||||
|
||||
void PNS_ROUTER::markViolations( PNS_NODE* aNode, PNS_ITEMSET& aCurrent,
|
||||
PNS_NODE::ITEM_VECTOR& aRemoved )
|
||||
{
|
||||
|
||||
BOOST_FOREACH(PNS_ITEM *item, aCurrent.Items())
|
||||
BOOST_FOREACH( PNS_ITEM *item, aCurrent.Items() )
|
||||
{
|
||||
PNS_NODE::Obstacles obstacles;
|
||||
PNS_NODE::OBSTACLES obstacles;
|
||||
|
||||
aNode->QueryColliding( item, obstacles, PNS_ITEM::ANY );
|
||||
|
||||
if ( item->OfKind(PNS_ITEM::LINE ) )
|
||||
if( item->OfKind( PNS_ITEM::LINE ) )
|
||||
{
|
||||
PNS_LINE *l = static_cast<PNS_LINE *> (item);
|
||||
if (l->EndsWithVia())
|
||||
PNS_LINE *l = static_cast<PNS_LINE*>( item );
|
||||
|
||||
if( l->EndsWithVia() )
|
||||
{
|
||||
PNS_VIA v ( l->Via() );
|
||||
aNode->QueryColliding(&v , obstacles, PNS_ITEM::ANY );
|
||||
aNode->QueryColliding( &v, obstacles, PNS_ITEM::ANY );
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_FOREACH(PNS_OBSTACLE& obs, obstacles)
|
||||
BOOST_FOREACH( PNS_OBSTACLE& obs, obstacles )
|
||||
{
|
||||
int clearance = aNode->GetClearance( item, obs.item );
|
||||
std::auto_ptr<PNS_ITEM> tmp ( obs.item->Clone() );
|
||||
tmp->Mark ( MK_VIOLATION );
|
||||
int clearance = aNode->GetClearance( item, obs.m_item );
|
||||
std::auto_ptr<PNS_ITEM> tmp( obs.m_item->Clone() );
|
||||
tmp->Mark( MK_VIOLATION );
|
||||
DisplayItem( tmp.get(), -1, clearance );
|
||||
aRemoved.push_back(obs.item);
|
||||
aRemoved.push_back( obs.m_item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PNS_ROUTER::updateView( PNS_NODE *aNode, PNS_ITEMSET& aCurrent )
|
||||
|
||||
void PNS_ROUTER::updateView( PNS_NODE* aNode, PNS_ITEMSET& aCurrent )
|
||||
{
|
||||
PNS_NODE::ItemVector removed, added;
|
||||
PNS_NODE::Obstacles obstacles;
|
||||
PNS_NODE::ITEM_VECTOR removed, added;
|
||||
PNS_NODE::OBSTACLES obstacles;
|
||||
|
||||
if(!aNode)
|
||||
if( !aNode )
|
||||
return;
|
||||
|
||||
if( Settings().Mode() == RM_MarkObstacles )
|
||||
|
@ -661,15 +665,14 @@ void PNS_ROUTER::ApplySettings()
|
|||
m_placer->Move( m_currentEnd, m_currentEndItem );
|
||||
movePlacing( m_currentEnd, m_currentEndItem );
|
||||
}
|
||||
|
||||
// TODO handle mode/optimization/other options change
|
||||
}
|
||||
|
||||
void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* endItem )
|
||||
|
||||
void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
||||
{
|
||||
eraseView();
|
||||
|
||||
m_placer->Move( aP, endItem );
|
||||
m_placer->Move( aP, aEndItem );
|
||||
PNS_LINE current = m_placer->Trace();
|
||||
|
||||
DisplayItem( ¤t );
|
||||
|
@ -681,9 +684,10 @@ void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* endItem )
|
|||
updateView ( m_placer->CurrentNode ( true ), tmp );
|
||||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::CommitRouting( PNS_NODE* aNode )
|
||||
{
|
||||
PNS_NODE::ItemVector removed, added;
|
||||
PNS_NODE::ITEM_VECTOR removed, added;
|
||||
|
||||
aNode->GetUpdatedItems( removed, added );
|
||||
|
||||
|
@ -706,31 +710,31 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode )
|
|||
switch( item->Kind() )
|
||||
{
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
|
||||
TRACK* track = new TRACK( m_board );
|
||||
const SEG& s = seg->Seg();
|
||||
{
|
||||
PNS_SEGMENT* seg = static_cast<PNS_SEGMENT*>( item );
|
||||
TRACK* track = new TRACK( m_board );
|
||||
const SEG& s = seg->Seg();
|
||||
|
||||
track->SetStart( wxPoint( s.A.x, s.A.y ) );
|
||||
track->SetEnd( wxPoint( s.B.x, s.B.y ) );
|
||||
track->SetWidth( seg->Width() );
|
||||
track->SetLayer( seg->Layers().Start() );
|
||||
track->SetNetCode( seg->Net() );
|
||||
newBI = track;
|
||||
break;
|
||||
}
|
||||
track->SetStart( wxPoint( s.A.x, s.A.y ) );
|
||||
track->SetEnd( wxPoint( s.B.x, s.B.y ) );
|
||||
track->SetWidth( seg->Width() );
|
||||
track->SetLayer( seg->Layers().Start() );
|
||||
track->SetNetCode( seg->Net() );
|
||||
newBI = track;
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
{
|
||||
VIA* via_board = new VIA( m_board );
|
||||
PNS_VIA* via = static_cast<PNS_VIA*>( item );
|
||||
via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
|
||||
via_board->SetWidth( via->Diameter() );
|
||||
via_board->SetDrill( via->Drill() );
|
||||
via_board->SetNetCode( via->Net() );
|
||||
newBI = via_board;
|
||||
break;
|
||||
}
|
||||
{
|
||||
VIA* via_board = new VIA( m_board );
|
||||
PNS_VIA* via = static_cast<PNS_VIA*>( item );
|
||||
via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) );
|
||||
via_board->SetWidth( via->Diameter() );
|
||||
via_board->SetDrill( via->Drill() );
|
||||
via_board->SetNetCode( via->Net() );
|
||||
newBI = via_board;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -770,34 +774,33 @@ PNS_VIA* PNS_ROUTER::checkLoneVia( PNS_JOINT* aJoint ) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool PNS_ROUTER::FixRoute( const VECTOR2I& aP, PNS_ITEM* aEndItem )
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
switch(m_state)
|
||||
switch( m_state )
|
||||
{
|
||||
case ROUTE_TRACK:
|
||||
rv = m_placer->FixRoute (aP, aEndItem);
|
||||
rv = m_placer->FixRoute( aP, aEndItem );
|
||||
m_placingVia = false;
|
||||
|
||||
break;
|
||||
|
||||
case DRAG_SEGMENT:
|
||||
rv = m_dragger->FixRoute ();
|
||||
rv = m_dragger->FixRoute();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(rv)
|
||||
if( rv )
|
||||
StopRouting();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PNS_ROUTER::StopRouting()
|
||||
{
|
||||
// Update the ratsnest with new changes
|
||||
|
@ -806,10 +809,10 @@ void PNS_ROUTER::StopRouting()
|
|||
if( !RoutingInProgress() )
|
||||
return;
|
||||
|
||||
if(m_placer)
|
||||
if( m_placer )
|
||||
delete m_placer;
|
||||
|
||||
if(m_dragger)
|
||||
if( m_dragger )
|
||||
delete m_dragger;
|
||||
|
||||
m_placer = NULL;
|
||||
|
@ -825,7 +828,7 @@ void PNS_ROUTER::StopRouting()
|
|||
|
||||
void PNS_ROUTER::FlipPosture()
|
||||
{
|
||||
if(m_state == ROUTE_TRACK)
|
||||
if( m_state == ROUTE_TRACK )
|
||||
{
|
||||
m_placer->FlipPosture();
|
||||
m_placer->Move ( m_currentEnd, m_currentEndItem );
|
||||
|
@ -833,22 +836,23 @@ void PNS_ROUTER::FlipPosture()
|
|||
}
|
||||
|
||||
|
||||
void PNS_ROUTER::SwitchLayer( int layer )
|
||||
void PNS_ROUTER::SwitchLayer( int aLayer )
|
||||
{
|
||||
switch( m_state )
|
||||
{
|
||||
case IDLE:
|
||||
m_currentLayer = layer;
|
||||
m_currentLayer = aLayer;
|
||||
break;
|
||||
|
||||
case ROUTE_TRACK:
|
||||
if( m_startsOnVia )
|
||||
{
|
||||
m_currentLayer = layer;
|
||||
//m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth,
|
||||
// m_currentLayer );
|
||||
}
|
||||
break;
|
||||
if( m_startsOnVia )
|
||||
{
|
||||
m_currentLayer = aLayer;
|
||||
//m_placer->StartPlacement( m_currentStart, m_currentNet, m_currentWidth,
|
||||
// m_currentLayer );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -864,32 +868,38 @@ void PNS_ROUTER::ToggleViaPlacement()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
int PNS_ROUTER::GetCurrentNet() const
|
||||
{
|
||||
switch(m_state)
|
||||
switch( m_state )
|
||||
{
|
||||
case ROUTE_TRACK:
|
||||
return m_placer->CurrentNet();
|
||||
|
||||
default:
|
||||
return m_currentNet;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PNS_ROUTER::GetCurrentLayer() const
|
||||
{
|
||||
switch(m_state)
|
||||
switch( m_state )
|
||||
{
|
||||
case ROUTE_TRACK:
|
||||
return m_placer->CurrentLayer();
|
||||
|
||||
default:
|
||||
return m_currentLayer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PNS_ROUTER::DumpLog()
|
||||
{
|
||||
PNS_LOGGER *logger = NULL;
|
||||
switch(m_state)
|
||||
PNS_LOGGER* logger = NULL;
|
||||
|
||||
switch( m_state )
|
||||
{
|
||||
case DRAG_SEGMENT:
|
||||
logger = m_dragger->Logger();
|
||||
|
@ -899,6 +909,6 @@ void PNS_ROUTER::DumpLog()
|
|||
break;
|
||||
}
|
||||
|
||||
if(logger)
|
||||
if( logger )
|
||||
logger->Save ( "/tmp/shove.log" );
|
||||
}
|
||||
|
|
|
@ -51,9 +51,10 @@ class PNS_CLEARANCE_FUNC;
|
|||
class PNS_SHOVE;
|
||||
class PNS_DRAGGER;
|
||||
|
||||
namespace KIGFX {
|
||||
class VIEW;
|
||||
class VIEW_GROUP;
|
||||
namespace KIGFX
|
||||
{
|
||||
class VIEW;
|
||||
class VIEW_GROUP;
|
||||
};
|
||||
|
||||
|
||||
|
@ -62,7 +63,6 @@ class VIEW_GROUP;
|
|||
*
|
||||
* Main router class.
|
||||
*/
|
||||
|
||||
class PNS_ROUTER
|
||||
{
|
||||
private:
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
|
||||
const VECTOR2I CurrentEnd() const;
|
||||
|
||||
int GetClearance( const PNS_ITEM* a, const PNS_ITEM* b ) const;
|
||||
int GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const;
|
||||
|
||||
PNS_NODE* GetWorld() const
|
||||
{
|
||||
|
@ -114,8 +114,8 @@ public:
|
|||
|
||||
void ToggleViaPlacement();
|
||||
|
||||
int GetCurrentLayer() const;// { return m_currentLayer; }
|
||||
int GetCurrentNet() const;// { return m_currentNet; }
|
||||
int GetCurrentLayer() const;
|
||||
int GetCurrentNet() const;
|
||||
|
||||
void DumpLog();
|
||||
|
||||
|
@ -134,14 +134,19 @@ public:
|
|||
// typedef boost::optional<hoverItem> optHoverItem;
|
||||
|
||||
const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP );
|
||||
const VECTOR2I SnapToItem( PNS_ITEM* item, VECTOR2I aP, bool& aSplitsSegment );
|
||||
const VECTOR2I SnapToItem( PNS_ITEM* aItem, VECTOR2I aP, bool& aSplitsSegment );
|
||||
|
||||
bool StartDragging( const VECTOR2I& aP, PNS_ITEM* aItem );
|
||||
|
||||
void SetIterLimit( int aX ) { m_iterLimit = aX; }
|
||||
int GetIterLimit() const { return m_iterLimit; };
|
||||
|
||||
void SetShowIntermediateSteps(bool aX, int aSnapshotIter = -1 ) { m_showInterSteps = aX; m_snapshotIter = aSnapshotIter; }
|
||||
void SetShowIntermediateSteps( bool aX, int aSnapshotIter = -1 )
|
||||
{
|
||||
m_showInterSteps = aX;
|
||||
m_snapshotIter = aSnapshotIter;
|
||||
}
|
||||
|
||||
bool GetShowIntermediateSteps() const { return m_showInterSteps; }
|
||||
int GetShapshotIter() const { return m_snapshotIter; }
|
||||
|
||||
|
@ -168,7 +173,7 @@ public:
|
|||
|
||||
/**
|
||||
* Applies stored settings.
|
||||
* \see Settings()
|
||||
* @see Settings()
|
||||
*/
|
||||
void ApplySettings();
|
||||
|
||||
|
@ -183,30 +188,29 @@ public:
|
|||
ApplySettings();
|
||||
}
|
||||
|
||||
void EnableSnapping ( bool aEnable )
|
||||
void EnableSnapping( bool aEnable )
|
||||
{
|
||||
m_snappingEnabled = aEnable;
|
||||
}
|
||||
|
||||
bool SnappingEnabled () const
|
||||
bool SnappingEnabled() const
|
||||
{
|
||||
return m_snappingEnabled;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
void movePlacing ( const VECTOR2I& aP, PNS_ITEM* aItem );
|
||||
void moveDragging ( const VECTOR2I& aP, PNS_ITEM* aItem );
|
||||
void movePlacing( const VECTOR2I& aP, PNS_ITEM* aItem );
|
||||
void moveDragging( const VECTOR2I& aP, PNS_ITEM* aItem );
|
||||
|
||||
void eraseView();
|
||||
void updateView( PNS_NODE *aNode, PNS_ITEMSET &aCurrent ); //PNS_LINE *aCurrent = NULL );
|
||||
void updateView( PNS_NODE* aNode, PNS_ITEMSET& aCurrent );
|
||||
|
||||
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);
|
||||
PNS_ITEM* pickSingleItem( PNS_ITEMSET& aItems ) const;
|
||||
void splitAdjacentSegments( PNS_NODE* aNode, PNS_ITEM* aSeg, const VECTOR2I& aP );
|
||||
PNS_VIA* checkLoneVia( PNS_JOINT* aJoint ) const;
|
||||
|
||||
PNS_ITEM* syncPad( D_PAD* aPad );
|
||||
|
@ -219,7 +223,7 @@ private:
|
|||
|
||||
void highlightCurrent( bool enabled );
|
||||
|
||||
void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ItemVector& aRemoved );
|
||||
void markViolations( PNS_NODE *aNode, PNS_ITEMSET& aCurrent, PNS_NODE::ITEM_VECTOR& aRemoved );
|
||||
|
||||
int m_currentLayer;
|
||||
int m_currentNet;
|
||||
|
@ -241,8 +245,7 @@ private:
|
|||
KIGFX::VIEW* m_view;
|
||||
KIGFX::VIEW_GROUP* m_previewItems;
|
||||
|
||||
|
||||
PNS_ITEM *m_currentEndItem;
|
||||
PNS_ITEM* m_currentEndItem;
|
||||
|
||||
VECTOR2I m_currentEnd;
|
||||
VECTOR2I m_currentStart;
|
||||
|
@ -252,7 +255,7 @@ private:
|
|||
bool m_snappingEnabled;
|
||||
bool m_violation;
|
||||
|
||||
// optHoverItem m_startItem, m_endItem;
|
||||
// optHoverItem m_startItem, m_endItem;
|
||||
|
||||
PNS_ROUTING_SETTINGS m_settings;
|
||||
PNS_CLEARANCE_FUNC* m_clearanceFunc;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS()
|
||||
{
|
||||
m_routingMode = RM_Walkaround;
|
||||
m_optimizerEffort = OE_Full;
|
||||
m_optimizerEffort = OE_FULL;
|
||||
m_removeLoops = true;
|
||||
m_smartPads = true;
|
||||
m_shoveVias = true;
|
||||
|
@ -38,11 +38,13 @@ PNS_ROUTING_SETTINGS::PNS_ROUTING_SETTINGS()
|
|||
m_canViolateDRC = false;
|
||||
}
|
||||
|
||||
|
||||
TIME_LIMIT PNS_ROUTING_SETTINGS::ShoveTimeLimit() const
|
||||
{
|
||||
return TIME_LIMIT ( m_shoveTimeLimit );
|
||||
}
|
||||
|
||||
|
||||
int PNS_ROUTING_SETTINGS::ShoveIterationLimit() const
|
||||
{
|
||||
return m_shoveIterationLimit;
|
||||
|
|
|
@ -36,9 +36,9 @@ enum PNS_MODE
|
|||
///> Optimization effort
|
||||
enum PNS_OPTIMIZATION_EFFORT
|
||||
{
|
||||
OE_Low = 0,
|
||||
OE_Medium = 1,
|
||||
OE_Full = 2
|
||||
OE_LOW = 0,
|
||||
OE_MEDIUM = 1,
|
||||
OE_FULL = 2
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -91,7 +91,7 @@ public:
|
|||
///> Returns true if follow mouse mode is active (permanently on for the moment).
|
||||
bool FollowMouse() const
|
||||
{
|
||||
return m_followMouse && !(Mode() == RM_MarkObstacles);
|
||||
return m_followMouse && !( Mode() == RM_MarkObstacles );
|
||||
}
|
||||
|
||||
///> Returns true if smoothing segments durign dragging is enabled.
|
||||
|
@ -120,10 +120,10 @@ public:
|
|||
|
||||
const DIRECTION_45 InitialDirection() const
|
||||
{
|
||||
if(m_startDiagonal)
|
||||
return DIRECTION_45 (DIRECTION_45::NE);
|
||||
if( m_startDiagonal )
|
||||
return DIRECTION_45( DIRECTION_45::NE );
|
||||
else
|
||||
return DIRECTION_45 (DIRECTION_45::N);
|
||||
return DIRECTION_45( DIRECTION_45::N );
|
||||
}
|
||||
|
||||
int ShoveIterationLimit() const;
|
||||
|
@ -133,7 +133,6 @@ public:
|
|||
TIME_LIMIT WalkaroundTimeLimit() const;
|
||||
|
||||
private:
|
||||
|
||||
bool m_shoveVias;
|
||||
bool m_startDiagonal;
|
||||
bool m_removeLoops;
|
||||
|
|
|
@ -37,17 +37,17 @@ class PNS_SEGMENT : public PNS_ITEM
|
|||
public:
|
||||
PNS_SEGMENT() :
|
||||
PNS_ITEM( SEGMENT )
|
||||
{};
|
||||
{}
|
||||
|
||||
PNS_SEGMENT( const SEG& aSeg, int aNet ) :
|
||||
PNS_ITEM( SEGMENT ), m_seg(aSeg, 0)
|
||||
PNS_ITEM( SEGMENT ), m_seg( aSeg, 0 )
|
||||
{
|
||||
m_net = aNet;
|
||||
};
|
||||
}
|
||||
|
||||
PNS_SEGMENT( const PNS_LINE& aParentLine, const SEG& aSeg ) :
|
||||
PNS_ITEM( SEGMENT ),
|
||||
m_seg(aSeg, aParentLine.Width())
|
||||
m_seg( aSeg, aParentLine.Width() )
|
||||
{
|
||||
m_net = aParentLine.Net();
|
||||
m_layers = aParentLine.Layers();
|
||||
|
@ -55,7 +55,6 @@ public:
|
|||
m_rank = aParentLine.Rank();
|
||||
};
|
||||
|
||||
|
||||
PNS_SEGMENT* Clone( ) const;
|
||||
|
||||
const SHAPE* Shape() const
|
||||
|
@ -101,14 +100,14 @@ public:
|
|||
void SwapEnds()
|
||||
{
|
||||
SEG tmp = m_seg.GetSeg();
|
||||
m_seg.SetSeg( SEG (tmp.B , tmp.A ));
|
||||
m_seg.SetSeg( SEG (tmp.B , tmp.A ) );
|
||||
}
|
||||
|
||||
const SHAPE_LINE_CHAIN Hull( int aClearance, int aWalkaroundThickness ) const;
|
||||
|
||||
virtual VECTOR2I Anchor(int n) const
|
||||
{
|
||||
if(n == 0)
|
||||
if( n == 0 )
|
||||
return m_seg.GetSeg().A;
|
||||
else
|
||||
return m_seg.GetSeg().B;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -44,7 +44,7 @@ class PNS_SHOVE : public PNS_ALGO_BASE
|
|||
{
|
||||
public:
|
||||
|
||||
enum ShoveStatus
|
||||
enum SHOVE_STATUS
|
||||
{
|
||||
SH_OK = 0,
|
||||
SH_NULL,
|
||||
|
@ -52,72 +52,74 @@ public:
|
|||
SH_HEAD_MODIFIED
|
||||
};
|
||||
|
||||
PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER *aRouter );
|
||||
PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter );
|
||||
~PNS_SHOVE();
|
||||
|
||||
virtual PNS_LOGGER *Logger()
|
||||
virtual PNS_LOGGER* Logger()
|
||||
{
|
||||
return &m_logger;
|
||||
}
|
||||
|
||||
ShoveStatus ShoveLines( const PNS_LINE& aCurrentHead );
|
||||
ShoveStatus ShoveDraggingVia ( PNS_VIA *aVia, const VECTOR2I& aWhere, PNS_VIA **aNewVia );
|
||||
SHOVE_STATUS ShoveLines( const PNS_LINE& aCurrentHead );
|
||||
SHOVE_STATUS ShoveDraggingVia( PNS_VIA*aVia, const VECTOR2I& aWhere, PNS_VIA** aNewVia );
|
||||
|
||||
PNS_NODE* CurrentNode();
|
||||
|
||||
const PNS_LINE NewHead() const;
|
||||
|
||||
void SetInitialLine ( PNS_LINE *aInitial );
|
||||
void SetInitialLine ( PNS_LINE* aInitial );
|
||||
|
||||
private:
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> HullSet;
|
||||
typedef boost::optional<PNS_LINE> OptLine;
|
||||
typedef std::pair <PNS_LINE *, PNS_LINE *> LinePair;
|
||||
typedef std::vector<LinePair> LinePairVec;
|
||||
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
|
||||
typedef boost::optional<PNS_LINE> OPT_LINE;
|
||||
typedef std::pair <PNS_LINE*, PNS_LINE*> LINE_PAIR;
|
||||
typedef std::vector<LINE_PAIR> LINE_PAIR_VEC;
|
||||
|
||||
struct SpringbackTag
|
||||
struct SPRINGBACK_TAG
|
||||
{
|
||||
int64_t length;
|
||||
int segments;
|
||||
VECTOR2I p;
|
||||
PNS_NODE *node;
|
||||
PNS_ITEMSET headItems;
|
||||
PNS_COST_ESTIMATOR cost;
|
||||
int64_t m_length;
|
||||
int m_segments;
|
||||
VECTOR2I m_p;
|
||||
PNS_NODE* m_node;
|
||||
PNS_ITEMSET m_headItems;
|
||||
PNS_COST_ESTIMATOR m_cost;
|
||||
};
|
||||
|
||||
ShoveStatus processSingleLine(PNS_LINE *aCurrent, PNS_LINE* aObstacle, PNS_LINE *aShoved );
|
||||
ShoveStatus processHullSet ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved, const HullSet& hulls );
|
||||
SHOVE_STATUS processSingleLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved );
|
||||
SHOVE_STATUS processHullSet( PNS_LINE* aCurrent, PNS_LINE* aObstacle,
|
||||
PNS_LINE* aShoved, const HULL_SET& hulls );
|
||||
|
||||
bool reduceSpringback( const PNS_ITEMSET &aHeadItems );
|
||||
bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET &aHeadItems, const PNS_COST_ESTIMATOR& aCost );
|
||||
bool reduceSpringback( const PNS_ITEMSET& aHeadItems );
|
||||
bool pushSpringback( PNS_NODE* aNode, const PNS_ITEMSET &aHeadItems,
|
||||
const PNS_COST_ESTIMATOR& aCost );
|
||||
|
||||
ShoveStatus walkaroundLoneVia ( PNS_LINE *aCurrent, PNS_LINE *aObstacle, PNS_LINE *aShoved );
|
||||
bool checkBumpDirection ( PNS_LINE *aCurrent, PNS_LINE *aShoved ) const;
|
||||
SHOVE_STATUS walkaroundLoneVia( PNS_LINE* aCurrent, PNS_LINE* aObstacle, PNS_LINE* aShoved );
|
||||
bool checkBumpDirection( PNS_LINE* aCurrent, PNS_LINE* aShoved ) const;
|
||||
|
||||
ShoveStatus onCollidingLine( PNS_LINE *aCurrent, PNS_LINE *aObstacle );
|
||||
ShoveStatus onCollidingSegment( PNS_LINE *aCurrent, PNS_SEGMENT *aObstacleSeg );
|
||||
ShoveStatus onCollidingSolid( PNS_LINE *aCurrent, PNS_SOLID *aObstacleSolid );
|
||||
ShoveStatus onCollidingVia( PNS_ITEM *aCurrent, PNS_VIA *aObstacleVia );
|
||||
ShoveStatus onReverseCollidingVia( PNS_LINE *aCurrent, PNS_VIA *aObstacleVia );
|
||||
ShoveStatus pushVia ( PNS_VIA *aVia, const VECTOR2I& aForce, int aCurrentRank );
|
||||
SHOVE_STATUS onCollidingLine( PNS_LINE* aCurrent, PNS_LINE* aObstacle );
|
||||
SHOVE_STATUS onCollidingSegment( PNS_LINE* aCurrent, PNS_SEGMENT* aObstacleSeg );
|
||||
SHOVE_STATUS onCollidingSolid( PNS_LINE* aCurrent, PNS_SOLID* aObstacleSolid );
|
||||
SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia );
|
||||
SHOVE_STATUS onReverseCollidingVia( PNS_LINE* aCurrent, PNS_VIA* aObstacleVia );
|
||||
SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank );
|
||||
|
||||
void unwindStack ( PNS_SEGMENT *seg );
|
||||
void unwindStack ( PNS_ITEM *item );
|
||||
void unwindStack( PNS_SEGMENT* aSeg );
|
||||
void unwindStack( PNS_ITEM *aItem );
|
||||
|
||||
void runOptimizer ( PNS_NODE *node, PNS_LINE *head );
|
||||
void runOptimizer( PNS_NODE* aNode, PNS_LINE* aHead );
|
||||
|
||||
void pushLine ( PNS_LINE *l );
|
||||
void pushLine( PNS_LINE *aL );
|
||||
void popLine();
|
||||
|
||||
const RANGE<int> findShovedVertexRange ( PNS_LINE *l );
|
||||
const RANGE<int> findShovedVertexRange( PNS_LINE *aL );
|
||||
|
||||
PNS_LINE *assembleLine ( const PNS_SEGMENT *aSeg, int *aIndex = NULL );
|
||||
PNS_LINE *cloneLine ( const PNS_LINE *aLine );
|
||||
PNS_LINE* assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL );
|
||||
PNS_LINE* cloneLine( const PNS_LINE* aLine );
|
||||
|
||||
ShoveStatus shoveIteration(int aIter);
|
||||
ShoveStatus shoveMainLoop();
|
||||
SHOVE_STATUS shoveIteration( int aIter );
|
||||
SHOVE_STATUS shoveMainLoop();
|
||||
|
||||
std::vector<SpringbackTag> m_nodeStack;
|
||||
std::vector<SPRINGBACK_TAG> m_nodeStack;
|
||||
std::vector<PNS_LINE*> m_lineStack;
|
||||
std::vector<PNS_LINE*> m_optimizerQueue;
|
||||
std::vector<PNS_ITEM*> m_gcItems;
|
||||
|
@ -127,7 +129,7 @@ private:
|
|||
PNS_LINE* m_currentHead;
|
||||
PNS_LINE* m_collidingLine;
|
||||
|
||||
OptLine m_newHead;
|
||||
OPT_LINE m_newHead;
|
||||
|
||||
PNS_LOGGER m_logger;
|
||||
PNS_VIA* m_draggedVia;
|
||||
|
|
|
@ -30,29 +30,29 @@
|
|||
|
||||
const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness ) const
|
||||
{
|
||||
int cl = aClearance + aWalkaroundThickness / 2;
|
||||
int cl = aClearance + aWalkaroundThickness / 2;
|
||||
|
||||
switch( m_shape->Type() )
|
||||
{
|
||||
case SH_RECT:
|
||||
{
|
||||
SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape );
|
||||
return OctagonalHull( rect->GetPosition(), rect->GetSize(),
|
||||
cl + 1, 0.2 * cl );
|
||||
}
|
||||
{
|
||||
SHAPE_RECT* rect = static_cast<SHAPE_RECT*>( m_shape );
|
||||
return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl );
|
||||
}
|
||||
|
||||
case SH_CIRCLE:
|
||||
{
|
||||
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
|
||||
int r = circle->GetRadius();
|
||||
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
|
||||
cl + 1, 0.52 * (r + cl) );
|
||||
}
|
||||
{
|
||||
SHAPE_CIRCLE* circle = static_cast<SHAPE_CIRCLE*>( m_shape );
|
||||
int r = circle->GetRadius();
|
||||
return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
|
||||
cl + 1, 0.52 * ( r + cl ) );
|
||||
}
|
||||
|
||||
case SH_SEGMENT:
|
||||
{
|
||||
SHAPE_SEGMENT *seg = static_cast<SHAPE_SEGMENT *> ( m_shape );
|
||||
return SegmentHull (*seg, aClearance, aWalkaroundThickness );
|
||||
}
|
||||
{
|
||||
SHAPE_SEGMENT* seg = static_cast<SHAPE_SEGMENT*> ( m_shape );
|
||||
return SegmentHull( *seg, aClearance, aWalkaroundThickness );
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -64,6 +64,6 @@ const SHAPE_LINE_CHAIN PNS_SOLID::Hull( int aClearance, int aWalkaroundThickness
|
|||
|
||||
PNS_ITEM* PNS_SOLID::Clone ( ) const
|
||||
{
|
||||
PNS_ITEM *solid = new PNS_SOLID ( *this );
|
||||
PNS_ITEM* solid = new PNS_SOLID( *this );
|
||||
return solid;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
m_pos = aSolid.m_pos;
|
||||
}
|
||||
|
||||
PNS_ITEM* Clone( ) const;
|
||||
PNS_ITEM* Clone() const;
|
||||
|
||||
const SHAPE* Shape() const { return m_shape; }
|
||||
|
||||
|
@ -73,7 +73,7 @@ public:
|
|||
m_pos = aCenter;
|
||||
}
|
||||
|
||||
virtual VECTOR2I Anchor(int n) const
|
||||
virtual VECTOR2I Anchor( int aN ) const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
@ -83,7 +83,6 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
VECTOR2I m_pos;
|
||||
SHAPE* m_shape;
|
||||
|
|
|
@ -24,10 +24,8 @@
|
|||
|
||||
#include <geometry/shape_segment.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;
|
||||
|
||||
|
@ -45,9 +43,9 @@ const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0,
|
|||
return s;
|
||||
}
|
||||
|
||||
const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg,
|
||||
int aClearance,
|
||||
int aWalkaroundThickness )
|
||||
|
||||
const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
|
||||
int aWalkaroundThickness )
|
||||
{
|
||||
int d = aSeg.GetWidth() / 2 + aClearance + aWalkaroundThickness / 2 + HULL_MARGIN;
|
||||
int x = (int)( 2.0 / ( 1.0 + M_SQRT2 ) * d );
|
||||
|
@ -81,14 +79,15 @@ const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg,
|
|||
return s;
|
||||
}
|
||||
|
||||
|
||||
SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg )
|
||||
{
|
||||
SHAPE_RECT r;
|
||||
|
||||
VECTOR2I delta ( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 );
|
||||
VECTOR2I p0 ( aSeg.GetSeg().A - delta );
|
||||
VECTOR2I p1 ( aSeg.GetSeg().B + delta );
|
||||
VECTOR2I delta( aSeg.GetWidth() / 2, aSeg.GetWidth() / 2 );
|
||||
VECTOR2I p0( aSeg.GetSeg().A - delta );
|
||||
VECTOR2I p1( aSeg.GetSeg().B + delta );
|
||||
|
||||
return SHAPE_RECT ( std::min(p0.x, p1.x), std::min(p0.y, p1.y),
|
||||
std::abs(p1.x - p0.x), std::abs(p1.y - p0.y ));
|
||||
}
|
||||
return SHAPE_RECT( std::min( p0.x, p1.x ), std::min( p0.y, p1.y ),
|
||||
std::abs( p1.x - p0.x ), std::abs( p1.y - p0.y ) );
|
||||
}
|
||||
|
|
|
@ -31,11 +31,10 @@
|
|||
/** Various utility functions */
|
||||
|
||||
const SHAPE_LINE_CHAIN OctagonalHull( const VECTOR2I& aP0, const VECTOR2I& aSize,
|
||||
int aClearance, int aChamfer );
|
||||
int aClearance, int aChamfer );
|
||||
|
||||
const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg,
|
||||
int aClearance,
|
||||
int aWalkaroundThickness );
|
||||
const SHAPE_LINE_CHAIN SegmentHull ( const SHAPE_SEGMENT& aSeg, int aClearance,
|
||||
int aWalkaroundThickness );
|
||||
|
||||
SHAPE_RECT ApproximateSegmentAsRect( const SHAPE_SEGMENT& aSeg );
|
||||
|
||||
|
|
|
@ -25,26 +25,22 @@
|
|||
|
||||
#include <geometry/shape_rect.h>
|
||||
|
||||
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;
|
||||
PNS_VIA mv( *this );
|
||||
VECTOR2I force, totalForce, force2;
|
||||
|
||||
|
||||
while( iter < aMaxIterations )
|
||||
{
|
||||
|
||||
PNS_NODE::OptObstacle obs = aNode->CheckColliding( &mv, aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
|
||||
PNS_NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv,
|
||||
aSolidsOnly ? PNS_ITEM::SOLID : PNS_ITEM::ANY );
|
||||
|
||||
if( !obs )
|
||||
break;
|
||||
|
||||
int clearance = aNode->GetClearance( obs->item, &mv );
|
||||
int clearance = aNode->GetClearance( obs->m_item, &mv );
|
||||
|
||||
if( iter > aMaxIterations / 2 )
|
||||
{
|
||||
|
@ -53,14 +49,13 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode,
|
|||
mv.SetPos( mv.Pos() + l );
|
||||
}
|
||||
|
||||
bool col = CollideShapes( obs->item->Shape(), mv.Shape(), clearance, true, force2 );
|
||||
bool col = CollideShapes( obs->m_item->Shape(), mv.Shape(), clearance, true, force2 );
|
||||
|
||||
if(col) {
|
||||
if( col ) {
|
||||
totalForce += force2;
|
||||
mv.SetPos( mv.Pos() + force2 );
|
||||
}
|
||||
|
||||
|
||||
iter++;
|
||||
}
|
||||
|
||||
|
@ -68,19 +63,21 @@ bool PNS_VIA::PushoutForce( PNS_NODE* aNode,
|
|||
return false;
|
||||
|
||||
aForce = totalForce;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const SHAPE_LINE_CHAIN PNS_VIA::Hull( int aClearance, int aWalkaroundThickness ) const
|
||||
{
|
||||
int cl = (aClearance + aWalkaroundThickness / 2);
|
||||
int cl = ( aClearance + aWalkaroundThickness / 2 );
|
||||
|
||||
return OctagonalHull( m_pos -
|
||||
VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter,
|
||||
m_diameter ), cl + 1, (2 * cl + m_diameter) * 0.26 );
|
||||
VECTOR2I( m_diameter / 2, m_diameter / 2 ), VECTOR2I( m_diameter, m_diameter ),
|
||||
cl + 1, ( 2 * cl + m_diameter ) * 0.26 );
|
||||
}
|
||||
|
||||
|
||||
PNS_VIA* PNS_VIA::Clone ( ) const
|
||||
{
|
||||
PNS_VIA* v = new PNS_VIA();
|
||||
|
|
|
@ -32,7 +32,8 @@ class PNS_VIA : public PNS_ITEM
|
|||
{
|
||||
public:
|
||||
PNS_VIA() :
|
||||
PNS_ITEM( VIA ) {};
|
||||
PNS_ITEM( VIA )
|
||||
{}
|
||||
|
||||
PNS_VIA( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aDiameter, int aNet = -1 ) :
|
||||
PNS_ITEM( VIA )
|
||||
|
@ -42,21 +43,21 @@ public:
|
|||
m_pos = aPos;
|
||||
m_diameter = aDiameter;
|
||||
m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
PNS_VIA( const PNS_VIA& b ) :
|
||||
PNS_VIA( const PNS_VIA& aB ) :
|
||||
PNS_ITEM( VIA )
|
||||
{
|
||||
SetNet( b.Net() );
|
||||
SetLayers( b.Layers() );
|
||||
m_pos = b.m_pos;
|
||||
m_diameter = b.m_diameter;
|
||||
SetNet( aB.Net() );
|
||||
SetLayers( aB.Layers() );
|
||||
m_pos = aB.m_pos;
|
||||
m_diameter = aB.m_diameter;
|
||||
m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 );
|
||||
m_marker = b.m_marker;
|
||||
m_rank = b.m_rank;
|
||||
m_owner = b.m_owner;
|
||||
m_drill = b.m_drill;
|
||||
m_marker = aB.m_marker;
|
||||
m_rank = aB.m_rank;
|
||||
m_owner = aB.m_owner;
|
||||
m_drill = aB.m_drill;
|
||||
}
|
||||
|
||||
const VECTOR2I& Pos() const
|
||||
|
@ -106,7 +107,7 @@ public:
|
|||
|
||||
const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0 ) const;
|
||||
|
||||
virtual VECTOR2I Anchor(int n) const
|
||||
virtual VECTOR2I Anchor( int n ) const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
@ -117,7 +118,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_diameter;
|
||||
int m_drill;
|
||||
VECTOR2I m_pos;
|
||||
|
|
|
@ -32,22 +32,22 @@ using boost::optional;
|
|||
void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
|
||||
{
|
||||
m_iteration = 0;
|
||||
m_iteration_limit = 50;
|
||||
m_iterationLimit = 50;
|
||||
}
|
||||
|
||||
|
||||
PNS_NODE::OptObstacle PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
|
||||
PNS_NODE::OPT_OBSTACLE PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
|
||||
{
|
||||
return m_world->NearestObstacle( &aPath, m_item_mask);
|
||||
|
||||
return m_world->NearestObstacle( &aPath, m_itemMask );
|
||||
}
|
||||
|
||||
|
||||
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
||||
bool aWindingDirection )
|
||||
PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
||||
bool aWindingDirection )
|
||||
{
|
||||
optional<PNS_OBSTACLE>& current_obs =
|
||||
aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1];
|
||||
|
||||
bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1];
|
||||
|
||||
if( !current_obs )
|
||||
|
@ -55,15 +55,14 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
|||
|
||||
SHAPE_LINE_CHAIN path_pre[2], path_walk[2], path_post[2];
|
||||
|
||||
VECTOR2I last = aPath.CPoint( -1 );;
|
||||
VECTOR2I last = aPath.CPoint( -1 );
|
||||
|
||||
|
||||
if( ( current_obs->hull ).PointInside( last ) )
|
||||
if( ( current_obs->m_hull ).PointInside( last ) )
|
||||
{
|
||||
m_recursiveBlockageCount++;
|
||||
|
||||
if( m_recursiveBlockageCount < 3 )
|
||||
aPath.Line().Append( current_obs->hull.NearestPoint( last ) );
|
||||
aPath.Line().Append( current_obs->m_hull.NearestPoint( last ) );
|
||||
else
|
||||
{
|
||||
aPath = aPath.ClipToNearestObstacle( m_world );
|
||||
|
@ -71,17 +70,18 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
|||
}
|
||||
}
|
||||
|
||||
aPath.Walkaround( current_obs->hull, path_pre[0], path_walk[0],
|
||||
path_post[0], aWindingDirection );
|
||||
aPath.Walkaround( current_obs->hull, path_pre[1], path_walk[1],
|
||||
path_post[1], !aWindingDirection );
|
||||
aPath.Walkaround( current_obs->m_hull, path_pre[0], path_walk[0],
|
||||
path_post[0], aWindingDirection );
|
||||
aPath.Walkaround( current_obs->m_hull, path_pre[1], path_walk[1],
|
||||
path_post[1], !aWindingDirection );
|
||||
|
||||
#ifdef DEBUG
|
||||
m_logger.NewGroup (aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration);
|
||||
m_logger.Log ( &path_walk[0], 0, "path-walk");
|
||||
m_logger.Log ( &path_pre[0], 1, "path-pre");
|
||||
m_logger.Log ( &path_post[0], 4, "path-post");
|
||||
m_logger.Log ( ¤t_obs->hull, 2, "hull");
|
||||
m_logger.Log ( current_obs->item, 3, "item");
|
||||
m_logger.NewGroup( aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration );
|
||||
m_logger.Log( &path_walk[0], 0, "path-walk" );
|
||||
m_logger.Log( &path_pre[0], 1, "path-pre" );
|
||||
m_logger.Log( &path_post[0], 4, "path-post" );
|
||||
m_logger.Log( ¤t_obs->m_hull, 2, "hull" );
|
||||
m_logger.Log( current_obs->m_item, 3, "item" );
|
||||
#endif
|
||||
|
||||
int len_pre = path_walk[0].Length();
|
||||
|
@ -89,8 +89,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
|||
|
||||
PNS_LINE walk_path( aPath, path_walk[1] );
|
||||
|
||||
bool alt_collides = m_world->CheckColliding( &walk_path, m_item_mask );
|
||||
|
||||
bool alt_collides = m_world->CheckColliding( &walk_path, m_itemMask );
|
||||
|
||||
SHAPE_LINE_CHAIN pnew;
|
||||
|
||||
|
@ -127,15 +126,13 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
|||
}
|
||||
|
||||
|
||||
PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath,
|
||||
PNS_LINE& aWalkPath,
|
||||
bool aOptimize )
|
||||
PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::Route( const PNS_LINE& aInitialPath,
|
||||
PNS_LINE& aWalkPath, bool aOptimize )
|
||||
{
|
||||
PNS_LINE path_cw( aInitialPath ), path_ccw( aInitialPath );
|
||||
WalkaroundStatus s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
|
||||
WALKAROUND_STATUS s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
|
||||
SHAPE_LINE_CHAIN best_path;
|
||||
|
||||
|
||||
start( aInitialPath );
|
||||
|
||||
m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath );
|
||||
|
@ -143,7 +140,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
|
||||
aWalkPath = aInitialPath;
|
||||
|
||||
while( m_iteration < m_iteration_limit )
|
||||
while( m_iteration < m_iterationLimit )
|
||||
{
|
||||
if( s_cw != STUCK )
|
||||
s_cw = singleStep( path_cw, true );
|
||||
|
@ -155,7 +152,6 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
{
|
||||
int len_cw = path_cw.CLine().Length();
|
||||
int len_ccw = path_ccw.CLine().Length();
|
||||
|
||||
|
||||
if( m_forceLongerPath )
|
||||
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
|
||||
|
@ -178,16 +174,15 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
m_iteration++;
|
||||
}
|
||||
|
||||
if( m_iteration == m_iteration_limit )
|
||||
if( m_iteration == m_iterationLimit )
|
||||
{
|
||||
int len_cw = path_cw.CLine().Length();
|
||||
int len_ccw = path_ccw.CLine().Length();
|
||||
|
||||
|
||||
if( m_forceLongerPath )
|
||||
aWalkPath = (len_cw > len_ccw ? path_cw : path_ccw);
|
||||
aWalkPath = ( len_cw > len_ccw ? path_cw : path_ccw );
|
||||
else
|
||||
aWalkPath = (len_cw < len_ccw ? path_cw : path_ccw);
|
||||
aWalkPath = ( len_cw < len_ccw ? path_cw : path_ccw );
|
||||
}
|
||||
|
||||
if( m_cursorApproachMode )
|
||||
|
@ -226,16 +221,16 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::Route( const PNS_LINE& aInitial
|
|||
|
||||
aWalkPath.Line().Simplify();
|
||||
|
||||
if(aWalkPath.SegmentCount() < 1)
|
||||
if( aWalkPath.SegmentCount() < 1 )
|
||||
return STUCK;
|
||||
|
||||
if(aWalkPath.CPoint(-1) != aInitialPath.CPoint(-1))
|
||||
if( aWalkPath.CPoint( -1 ) != aInitialPath.CPoint( -1 ) )
|
||||
return STUCK;
|
||||
|
||||
if(aWalkPath.CPoint(0) != aInitialPath.CPoint(0))
|
||||
if( aWalkPath.CPoint( 0 ) != aInitialPath.CPoint( 0 ) )
|
||||
return STUCK;
|
||||
|
||||
WalkaroundStatus st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK;
|
||||
WALKAROUND_STATUS st = s_ccw == DONE || s_cw == DONE ? DONE : STUCK;
|
||||
|
||||
if( aOptimize && st == DONE )
|
||||
PNS_OPTIMIZER::Optimize( &aWalkPath, PNS_OPTIMIZER::MERGE_OBTUSE, m_world );
|
||||
|
|
|
@ -32,20 +32,20 @@ class PNS_WALKAROUND : public PNS_ALGO_BASE
|
|||
static const int DefaultIterationLimit = 50;
|
||||
|
||||
public:
|
||||
PNS_WALKAROUND( PNS_NODE* aWorld, PNS_ROUTER *aRouter ) :
|
||||
PNS_WALKAROUND( PNS_NODE* aWorld, PNS_ROUTER* aRouter ) :
|
||||
PNS_ALGO_BASE ( aRouter ),
|
||||
m_world( aWorld ),
|
||||
m_iteration_limit( DefaultIterationLimit )
|
||||
m_iterationLimit( DefaultIterationLimit )
|
||||
{
|
||||
m_forceSingleDirection = false;
|
||||
m_forceLongerPath = false;
|
||||
m_cursorApproachMode = false;
|
||||
m_item_mask = PNS_ITEM::ANY;
|
||||
};
|
||||
m_itemMask = PNS_ITEM::ANY;
|
||||
}
|
||||
|
||||
~PNS_WALKAROUND() {};
|
||||
|
||||
enum WalkaroundStatus
|
||||
enum WALKAROUND_STATUS
|
||||
{
|
||||
IN_PROGRESS = 0,
|
||||
DONE,
|
||||
|
@ -59,23 +59,23 @@ public:
|
|||
|
||||
void SetIterationLimit( const int aIterLimit )
|
||||
{
|
||||
m_iteration_limit = aIterLimit;
|
||||
m_iterationLimit = aIterLimit;
|
||||
}
|
||||
|
||||
void SetSolidsOnly( bool aSolidsOnly )
|
||||
{
|
||||
if(aSolidsOnly)
|
||||
m_item_mask = PNS_ITEM::SOLID;
|
||||
if( aSolidsOnly )
|
||||
m_itemMask = PNS_ITEM::SOLID;
|
||||
else
|
||||
m_item_mask = PNS_ITEM::ANY;
|
||||
m_itemMask = PNS_ITEM::ANY;
|
||||
}
|
||||
|
||||
void SetItemMask ( int aMask )
|
||||
void SetItemMask( int aMask )
|
||||
{
|
||||
m_item_mask = aMask;
|
||||
m_itemMask = aMask;
|
||||
}
|
||||
|
||||
void SetSingleDirection( bool aForceSingleDirection )
|
||||
void SetSingleDirection( bool aForceSingleDirection )
|
||||
{
|
||||
m_forceSingleDirection = aForceSingleDirection;
|
||||
m_forceLongerPath = aForceSingleDirection;
|
||||
|
@ -88,29 +88,30 @@ public:
|
|||
m_cursorApproachMode = aEnabled;
|
||||
}
|
||||
|
||||
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
|
||||
WALKAROUND_STATUS Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
|
||||
bool aOptimize = true );
|
||||
|
||||
virtual PNS_LOGGER *Logger() {
|
||||
virtual PNS_LOGGER* Logger()
|
||||
{
|
||||
return &m_logger;
|
||||
}
|
||||
|
||||
private:
|
||||
void start( const PNS_LINE& aInitialPath );
|
||||
|
||||
WalkaroundStatus singleStep( PNS_LINE& aPath, bool aWindingDirection );
|
||||
PNS_NODE::OptObstacle nearestObstacle( const PNS_LINE& aPath );
|
||||
WALKAROUND_STATUS singleStep( PNS_LINE& aPath, bool aWindingDirection );
|
||||
PNS_NODE::OPT_OBSTACLE nearestObstacle( const PNS_LINE& aPath );
|
||||
|
||||
PNS_NODE* m_world;
|
||||
|
||||
int m_recursiveBlockageCount;
|
||||
int m_iteration;
|
||||
int m_iteration_limit;
|
||||
int m_item_mask;
|
||||
int m_iterationLimit;
|
||||
int m_itemMask;
|
||||
bool m_forceSingleDirection, m_forceLongerPath;
|
||||
bool m_cursorApproachMode;
|
||||
VECTOR2I m_cursorPos;
|
||||
PNS_NODE::OptObstacle m_currentObstacle[2];
|
||||
PNS_NODE::OPT_OBSTACLE m_currentObstacle[2];
|
||||
bool m_recursiveCollision[2];
|
||||
PNS_LOGGER m_logger;
|
||||
};
|
||||
|
|
|
@ -21,16 +21,17 @@
|
|||
#ifndef __RANGE_H
|
||||
#define __RANGE_H
|
||||
|
||||
template<class T> class RANGE {
|
||||
|
||||
template<class T>
|
||||
class RANGE
|
||||
{
|
||||
public:
|
||||
RANGE (T aMin, T aMax) :
|
||||
m_min(aMin),
|
||||
m_max(aMax),
|
||||
m_defined(true) {}
|
||||
RANGE( T aMin, T aMax ) :
|
||||
m_min( aMin ),
|
||||
m_max( aMax ),
|
||||
m_defined( true ) {}
|
||||
|
||||
RANGE ():
|
||||
m_defined (false) {};
|
||||
RANGE():
|
||||
m_defined( false ) {}
|
||||
|
||||
T MinV() const
|
||||
{
|
||||
|
@ -42,36 +43,38 @@ template<class T> class RANGE {
|
|||
return m_max;
|
||||
}
|
||||
|
||||
void Set ( T aMin, T aMax ) const
|
||||
void Set( T aMin, T aMax ) const
|
||||
{
|
||||
m_max = aMax;
|
||||
m_min = aMin;
|
||||
}
|
||||
|
||||
void Grow ( T value )
|
||||
void Grow( T aValue )
|
||||
{
|
||||
if(!m_defined)
|
||||
if( !m_defined )
|
||||
{
|
||||
m_min = value;
|
||||
m_max = value;
|
||||
m_min = aValue;
|
||||
m_max = aValue;
|
||||
m_defined = true;
|
||||
} else {
|
||||
m_min = std::min(m_min, value);
|
||||
m_max = std::max(m_max, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_min = std::min( m_min, aValue );
|
||||
m_max = std::max( m_max, aValue );
|
||||
}
|
||||
}
|
||||
|
||||
bool Inside ( const T& value ) const
|
||||
bool Inside( const T& aValue ) const
|
||||
{
|
||||
if(!m_defined)
|
||||
if( !m_defined )
|
||||
return true;
|
||||
|
||||
return value >= m_min && value <= m_max;
|
||||
return aValue >= m_min && aValue <= m_max;
|
||||
}
|
||||
|
||||
bool Overlaps ( const RANGE<T> &aOther ) const
|
||||
bool Overlaps ( const RANGE<T>& aOther ) const
|
||||
{
|
||||
if(!m_defined || !aOther.m_defined)
|
||||
if( !m_defined || !aOther.m_defined )
|
||||
return true;
|
||||
|
||||
return m_max >= aOther.m_min && m_min <= aOther.m_max;
|
||||
|
@ -85,7 +88,6 @@ template<class T> class RANGE {
|
|||
private:
|
||||
T m_min, m_max;
|
||||
bool m_defined;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,6 @@ ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem, VIEW_GROUP* aPa
|
|||
m_clearance = -1;
|
||||
m_originLayer = m_layer = ITEM_GAL_LAYER ( GP_OVERLAY );
|
||||
|
||||
|
||||
if( aItem )
|
||||
Update( aItem );
|
||||
}
|
||||
|
@ -56,60 +55,59 @@ ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
|
|||
|
||||
void ROUTER_PREVIEW_ITEM::Update( const PNS_ITEM* aItem )
|
||||
{
|
||||
|
||||
m_originLayer = aItem->Layers().Start();
|
||||
|
||||
assert (m_originLayer >= 0);
|
||||
assert( m_originLayer >= 0 );
|
||||
|
||||
m_layer = m_originLayer;
|
||||
m_color = getLayerColor( m_originLayer );
|
||||
m_color.a = 0.8;
|
||||
m_depth = BaseOverlayDepth - aItem->Layers().Start();
|
||||
|
||||
m_shape = aItem->Shape()->Clone();
|
||||
|
||||
switch( aItem->Kind() )
|
||||
{
|
||||
case PNS_ITEM::LINE:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = ((PNS_LINE *) aItem)->Width();
|
||||
|
||||
break;
|
||||
case PNS_ITEM::LINE:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = ( (PNS_LINE*) aItem )->Width();
|
||||
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
PNS_SEGMENT *seg = (PNS_SEGMENT *)aItem;
|
||||
m_type = PR_SHAPE;
|
||||
m_width = seg->Width();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = 0;
|
||||
m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
|
||||
m_depth = ViaOverlayDepth;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SOLID:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = 0;
|
||||
break;
|
||||
case PNS_ITEM::SEGMENT:
|
||||
{
|
||||
PNS_SEGMENT* seg = (PNS_SEGMENT*) aItem;
|
||||
m_type = PR_SHAPE;
|
||||
m_width = seg->Width();
|
||||
break;
|
||||
}
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = 0;
|
||||
m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
|
||||
m_depth = ViaOverlayDepth;
|
||||
break;
|
||||
|
||||
case PNS_ITEM::SOLID:
|
||||
m_type = PR_SHAPE;
|
||||
m_width = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(aItem->Marker() & MK_VIOLATION)
|
||||
m_color = COLOR4D (0, 1, 0, 1);
|
||||
if( aItem->Marker() & MK_VIOLATION )
|
||||
m_color = COLOR4D( 0, 1, 0, 1 );
|
||||
|
||||
if(aItem->Marker() & MK_HEAD)
|
||||
m_color.Brighten(0.7);
|
||||
if( aItem->Marker() & MK_HEAD )
|
||||
m_color.Brighten( 0.7 );
|
||||
|
||||
ViewSetVisible( true );
|
||||
ViewUpdate( GEOMETRY | APPEARANCE );
|
||||
}
|
||||
|
||||
|
||||
const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
||||
{
|
||||
BOX2I bbox;
|
||||
|
@ -122,7 +120,7 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
|||
return bbox;
|
||||
|
||||
case PR_POINT:
|
||||
bbox = BOX2I ( m_pos - VECTOR2I(100000, 100000), VECTOR2I( 200000, 200000 ));
|
||||
bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
|
||||
return bbox;
|
||||
|
||||
default:
|
||||
|
@ -132,20 +130,23 @@ const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
|
|||
return bbox;
|
||||
}
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL* aGal ) const
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN &aL, KIGFX::GAL* aGal ) const
|
||||
{
|
||||
for( int s = 0; s < l.SegmentCount(); s++ )
|
||||
aGal->DrawLine( l.CSegment( s ).A, l.CSegment( s ).B );
|
||||
if( l.IsClosed() )
|
||||
aGal->DrawLine( l.CSegment( -1 ).B, l.CSegment( 0 ).A );
|
||||
for( int s = 0; s < aL.SegmentCount(); s++ )
|
||||
aGal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B );
|
||||
|
||||
if( aL.IsClosed() )
|
||||
aGal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A );
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
|
||||
{
|
||||
//col.Brighten(0.7);
|
||||
aGal->SetLayerDepth( m_depth );
|
||||
|
||||
if(m_type == PR_SHAPE)
|
||||
if( m_type == PR_SHAPE )
|
||||
{
|
||||
aGal->SetLineWidth( m_width );
|
||||
aGal->SetStrokeColor( m_color );
|
||||
|
@ -153,31 +154,29 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
|
|||
aGal->SetIsStroke( m_width ? true : false );
|
||||
aGal->SetIsFill( true );
|
||||
|
||||
|
||||
if(!m_shape)
|
||||
if( !m_shape )
|
||||
return;
|
||||
|
||||
switch( m_shape->Type() )
|
||||
{
|
||||
case SH_LINE_CHAIN:
|
||||
{
|
||||
const SHAPE_LINE_CHAIN *l = (const SHAPE_LINE_CHAIN *) m_shape;
|
||||
drawLineChain(*l, aGal);
|
||||
const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) m_shape;
|
||||
drawLineChain( *l, aGal );
|
||||
break;
|
||||
}
|
||||
|
||||
case SH_SEGMENT:
|
||||
{
|
||||
const SHAPE_SEGMENT *s = (const SHAPE_SEGMENT *) m_shape;
|
||||
const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) m_shape;
|
||||
aGal->DrawLine( s->GetSeg().A, s->GetSeg().B );
|
||||
|
||||
if(m_clearance > 0)
|
||||
if( m_clearance > 0 )
|
||||
{
|
||||
aGal->SetLayerDepth ( ClearanceOverlayDepth );
|
||||
aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY ));
|
||||
aGal->SetLayerDepth( ClearanceOverlayDepth );
|
||||
aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ));
|
||||
aGal->SetLineWidth( m_width + 2 * m_clearance );
|
||||
aGal->DrawLine( s->GetSeg().A, s->GetSeg().B );
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -185,13 +184,13 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
|
|||
|
||||
case SH_CIRCLE:
|
||||
{
|
||||
const SHAPE_CIRCLE *c = (const SHAPE_CIRCLE *) m_shape;
|
||||
const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) m_shape;
|
||||
aGal->DrawCircle( c->GetCenter(), c->GetRadius() );
|
||||
|
||||
if(m_clearance > 0)
|
||||
if( m_clearance > 0 )
|
||||
{
|
||||
aGal->SetLayerDepth ( ClearanceOverlayDepth );
|
||||
aGal->SetFillColor ( COLOR4D( DARKDARKGRAY ));
|
||||
aGal->SetLayerDepth( ClearanceOverlayDepth );
|
||||
aGal->SetFillColor( COLOR4D( DARKDARKGRAY ) );
|
||||
aGal->SetIsStroke( false );
|
||||
aGal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
|
||||
}
|
||||
|
@ -201,20 +200,20 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
|
|||
|
||||
case SH_RECT:
|
||||
{
|
||||
const SHAPE_RECT *r = (const SHAPE_RECT *) m_shape;
|
||||
aGal->DrawRectangle (r->GetPosition(), r->GetPosition() + r->GetSize());
|
||||
const SHAPE_RECT* r = (const SHAPE_RECT*) m_shape;
|
||||
aGal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
|
||||
|
||||
if(m_clearance > 0)
|
||||
if( m_clearance > 0 )
|
||||
{
|
||||
aGal->SetLayerDepth ( ClearanceOverlayDepth );
|
||||
VECTOR2I p0 (r -> GetPosition() ), s ( r->GetSize() );
|
||||
aGal->SetStrokeColor ( COLOR4D( DARKDARKGRAY ));
|
||||
aGal->SetLayerDepth( ClearanceOverlayDepth );
|
||||
VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
|
||||
aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) );
|
||||
aGal->SetIsStroke( true );
|
||||
aGal->SetLineWidth ( 2 * m_clearance );
|
||||
aGal->DrawLine( p0, VECTOR2I(p0.x + s.x, p0.y) );
|
||||
aGal->DrawLine( p0, VECTOR2I(p0.x, p0.y + s.y) );
|
||||
aGal->DrawLine( p0 + s , VECTOR2I(p0.x + s.x, p0.y) );
|
||||
aGal->DrawLine( p0 + s, VECTOR2I(p0.x, p0.y + s.y) );
|
||||
aGal->SetLineWidth( 2 * m_clearance );
|
||||
aGal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
|
||||
aGal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
|
||||
aGal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
|
||||
aGal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -224,9 +223,8 @@ void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::GAL* aGal ) const
|
|||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
|
||||
void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
|
||||
{
|
||||
|
||||
m_originLayer = m_layer = 0;
|
||||
m_width = aWidth;
|
||||
m_color = assignColor( aStyle );
|
||||
|
@ -234,15 +232,16 @@ void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int a
|
|||
m_depth = -2047;
|
||||
m_shape = aLine.Clone();
|
||||
|
||||
ViewSetVisible(true);
|
||||
ViewSetVisible( true );
|
||||
ViewUpdate( GEOMETRY | APPEARANCE );
|
||||
|
||||
}
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle )
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle )
|
||||
{
|
||||
}
|
||||
|
@ -251,7 +250,7 @@ void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle )
|
|||
const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
|
||||
{
|
||||
PCB_RENDER_SETTINGS* settings =
|
||||
static_cast <PCB_RENDER_SETTINGS*> ( m_parent->GetView()->GetPainter()->GetSettings() );
|
||||
static_cast<PCB_RENDER_SETTINGS*>( m_parent->GetView()->GetPainter()->GetSettings() );
|
||||
|
||||
return settings->GetLayerColor( aLayer );
|
||||
}
|
||||
|
|
|
@ -44,13 +44,12 @@ class PNS_ROUTER;
|
|||
class ROUTER_PREVIEW_ITEM : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
enum ItemType
|
||||
enum ITEM_TYPE
|
||||
{
|
||||
PR_STUCK_MARKER = 0,
|
||||
PR_POINT,
|
||||
PR_SHAPE
|
||||
};
|
||||
|
||||
|
||||
ROUTER_PREVIEW_ITEM( const PNS_ITEM* aItem = NULL, KIGFX::VIEW_GROUP* aParent = NULL );
|
||||
~ROUTER_PREVIEW_ITEM();
|
||||
|
@ -68,12 +67,12 @@ public:
|
|||
m_color = aColor;
|
||||
}
|
||||
|
||||
void SetClearance ( int aClearance )
|
||||
void SetClearance( int aClearance )
|
||||
{
|
||||
m_clearance = aClearance;
|
||||
}
|
||||
|
||||
void Show( int a, std::ostream& b ) const {};
|
||||
void Show( int aA, std::ostream& aB ) const {};
|
||||
|
||||
const BOX2I ViewBBox() const;
|
||||
|
||||
|
@ -85,7 +84,7 @@ public:
|
|||
aCount = 1;
|
||||
}
|
||||
|
||||
void drawLineChain( const SHAPE_LINE_CHAIN &l, KIGFX::GAL *aGal ) const;
|
||||
void drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL *aGal ) const;
|
||||
|
||||
private:
|
||||
const KIGFX::COLOR4D assignColor( int aStyle ) const;
|
||||
|
@ -94,9 +93,9 @@ private:
|
|||
KIGFX::VIEW_GROUP* m_parent;
|
||||
|
||||
PNS_ROUTER* m_router;
|
||||
SHAPE *m_shape;
|
||||
SHAPE* m_shape;
|
||||
|
||||
ItemType m_type;
|
||||
ITEM_TYPE m_type;
|
||||
|
||||
int m_style;
|
||||
int m_width;
|
||||
|
|
|
@ -82,35 +82,35 @@ ROUTER_TOOL::ROUTER_TOOL() :
|
|||
m_router = NULL;
|
||||
}
|
||||
|
||||
|
||||
class CONTEXT_TRACK_WIDTH_MENU: public CONTEXT_MENU
|
||||
{
|
||||
public:
|
||||
CONTEXT_TRACK_WIDTH_MENU()
|
||||
{
|
||||
setCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent, this, _1 ) );
|
||||
setCustomEventHandler( boost::bind( &CONTEXT_TRACK_WIDTH_MENU::handleCustomEvent,
|
||||
this, _1 ) );
|
||||
}
|
||||
|
||||
void SetBoard( BOARD* aBoard )
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS &bds = aBoard->GetDesignSettings();
|
||||
BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
|
||||
|
||||
wxString msg;
|
||||
m_board = aBoard;
|
||||
|
||||
Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ), wxEmptyString, wxITEM_CHECK );
|
||||
Append( ID_POPUP_PCB_SELECT_CUSTOM_WIDTH, _( "Custom size" ),
|
||||
wxEmptyString, wxITEM_CHECK );
|
||||
|
||||
Append( ID_POPUP_PCB_SELECT_AUTO_WIDTH, _( "Use the starting track width" ),
|
||||
_( "Route using the width of the starting track." ),
|
||||
wxITEM_CHECK );
|
||||
_( "Route using the width of the starting track." ), wxITEM_CHECK );
|
||||
|
||||
Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES,
|
||||
_( "Use netclass values" ),
|
||||
_( "Use track and via sizes from the net class" ),
|
||||
wxITEM_CHECK );
|
||||
Append( ID_POPUP_PCB_SELECT_USE_NETCLASS_VALUES, _( "Use netclass values" ),
|
||||
_( "Use track and via sizes from the net class" ), wxITEM_CHECK );
|
||||
|
||||
for( unsigned i = 0; i < bds.m_TrackWidthList.size(); i++ )
|
||||
{
|
||||
msg = _ ("Track ");
|
||||
msg = _( "Track ");
|
||||
msg << StringFromValue( g_UserUnit, bds.m_TrackWidthList[i], true );
|
||||
|
||||
if( i == 0 )
|
||||
|
@ -123,17 +123,18 @@ public:
|
|||
|
||||
for( unsigned i = 0; i < bds.m_ViasDimensionsList.size(); i++ )
|
||||
{
|
||||
msg = _ ("Via ");
|
||||
msg << StringFromValue( g_UserUnit, bds.m_ViasDimensionsList[i].m_Diameter,
|
||||
true );
|
||||
msg = _("Via ");
|
||||
msg << StringFromValue( g_UserUnit, bds.m_ViasDimensionsList[i].m_Diameter, true );
|
||||
wxString drill = StringFromValue( g_UserUnit,
|
||||
bds.m_ViasDimensionsList[i].m_Drill,
|
||||
true );
|
||||
bds.m_ViasDimensionsList[i].m_Drill,
|
||||
true );
|
||||
|
||||
if( bds.m_ViasDimensionsList[i].m_Drill <= 0 )
|
||||
{
|
||||
msg << _ (", drill: default");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
msg << _ (", drill: ") << drill;
|
||||
}
|
||||
|
||||
|
@ -148,7 +149,7 @@ protected:
|
|||
OPT_TOOL_EVENT handleCustomEvent( const wxEvent& aEvent )
|
||||
{
|
||||
#if ID_POPUP_PCB_SELECT_VIASIZE1 < ID_POPUP_PCB_SELECT_WIDTH1
|
||||
#error You have changed event ids, it breaks a piece of code. Lookup this line for more details.
|
||||
#error You have changed event ids order, it breaks code. Check the source code for more details.
|
||||
// Recognising type of event (track width/via size) is based on comparison if the event id is
|
||||
// within a specific range. If ranges of event ids changes, then the following is not valid anymore.
|
||||
#endif
|
||||
|
@ -156,7 +157,7 @@ protected:
|
|||
|
||||
int id = aEvent.GetId();
|
||||
|
||||
// General settings, to be modified below
|
||||
// Initial settings, to be modified below
|
||||
bds.m_UseConnectedTrackWidth = false;
|
||||
bds.UseCustomTrackViaSize( false );
|
||||
|
||||
|
@ -198,13 +199,10 @@ protected:
|
|||
};
|
||||
|
||||
|
||||
class CONTEXT_GRID_MENU: public CONTEXT_MENU { };
|
||||
|
||||
|
||||
class ROUTER_TOOL_MENU: public CONTEXT_MENU {
|
||||
|
||||
class ROUTER_TOOL_MENU: public CONTEXT_MENU
|
||||
{
|
||||
public:
|
||||
ROUTER_TOOL_MENU( BOARD *aBoard )
|
||||
ROUTER_TOOL_MENU( BOARD* aBoard )
|
||||
{
|
||||
SetTitle( wxT( "Interactive Router" ) );
|
||||
Add( ACT_NewTrack );
|
||||
|
@ -227,6 +225,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
ROUTER_TOOL::~ROUTER_TOOL()
|
||||
{
|
||||
delete m_router;
|
||||
|
@ -259,12 +258,13 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode )
|
|||
int w, d1, d2;
|
||||
|
||||
getNetclassDimensions( aNetCode, w, d1, d2 );
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::getNetclassDimensions( int aNetCode, int& aWidth,
|
||||
int& aViaDiameter, int& aViaDrill )
|
||||
int& aViaDiameter, int& aViaDrill )
|
||||
{
|
||||
BOARD* board = getModel<BOARD>( PCB_T );
|
||||
BOARD_DESIGN_SETTINGS &bds = board->GetDesignSettings();
|
||||
|
@ -316,29 +316,29 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
|
|||
{
|
||||
if( !prioritized[2] )
|
||||
prioritized[2] = item;
|
||||
if( item->Layers().Overlaps( tl ))
|
||||
if( item->Layers().Overlaps( tl ) )
|
||||
prioritized[0] = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !prioritized[3] )
|
||||
if( !prioritized[3] )
|
||||
prioritized[3] = item;
|
||||
if (item->Layers().Overlaps( tl ))
|
||||
if( item->Layers().Overlaps( tl ) )
|
||||
prioritized[1] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PNS_ITEM *rv = NULL;
|
||||
for(int i = 0; i < 4; i++)
|
||||
PNS_ITEM* rv = NULL;
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
PNS_ITEM *item = prioritized[i];
|
||||
PNS_ITEM* item = prioritized[i];
|
||||
|
||||
if( DisplayOpt.ContrastModeDisplay )
|
||||
if( item && !item->Layers().Overlaps( tl ) )
|
||||
item = NULL;
|
||||
|
||||
if(item)
|
||||
if( item )
|
||||
{
|
||||
rv = item;
|
||||
break;
|
||||
|
@ -349,12 +349,12 @@ PNS_ITEM* ROUTER_TOOL::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLa
|
|||
rv = NULL;
|
||||
|
||||
if( rv )
|
||||
TRACE( 0, "%s, layer : %d, tl: %d", rv->KindStr().c_str() % rv->Layers().Start() %
|
||||
tl );
|
||||
TRACE( 0, "%s, layer : %d, tl: %d", rv->KindStr().c_str() % rv->Layers().Start() % tl );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode )
|
||||
{
|
||||
RENDER_SETTINGS* rs = getView()->GetPainter()->GetSettings();
|
||||
|
@ -367,22 +367,23 @@ void ROUTER_TOOL::highlightNet( bool aEnabled, int aNetcode )
|
|||
getView()->UpdateAllLayersColor();
|
||||
}
|
||||
|
||||
void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt )
|
||||
|
||||
void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& aEvent )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if( evt.IsKeyPressed() )
|
||||
{
|
||||
switch( evt.KeyCode() )
|
||||
{
|
||||
case 'S':
|
||||
TRACEn(2, "saving drag/route log...\n");
|
||||
m_router->DumpLog();
|
||||
break;
|
||||
}
|
||||
if( aEvent.IsKeyPressed() )
|
||||
{
|
||||
switch( aEvent.KeyCode() )
|
||||
{
|
||||
case 'S':
|
||||
TRACEn( 2, "saving drag/route log...\n" );
|
||||
m_router->DumpLog();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( evt.IsAction( &ACT_RouterOptions ) )
|
||||
if( aEvent.IsAction( &ACT_RouterOptions ) )
|
||||
{
|
||||
DIALOG_PNS_SETTINGS settingsDlg( m_toolMgr->GetEditFrame(), m_router->Settings() );
|
||||
|
||||
|
@ -390,7 +391,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt )
|
|||
m_router->ApplySettings();
|
||||
}
|
||||
|
||||
else if( evt.IsAction( &ACT_CustomTrackWidth ) )
|
||||
else if( aEvent.IsAction( &ACT_CustomTrackWidth ) )
|
||||
{
|
||||
DIALOG_TRACK_VIA_SIZE sizeDlg( m_toolMgr->GetEditFrame(), m_router->Settings() );
|
||||
BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>( PCB_T )->GetDesignSettings();
|
||||
|
@ -410,7 +411,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt )
|
|||
handleCommonEvents( event );
|
||||
}
|
||||
|
||||
else if( evt.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) )
|
||||
else if( aEvent.IsAction( &COMMON_ACTIONS::trackViaSizeChanged ) )
|
||||
{
|
||||
BOARD_DESIGN_SETTINGS& bds = getModel<BOARD>( PCB_T )->GetDesignSettings();
|
||||
|
||||
|
@ -421,6 +422,7 @@ void ROUTER_TOOL::handleCommonEvents( TOOL_EVENT& evt )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
||||
{
|
||||
VIEW_CONTROLS* ctls = getViewControls();
|
||||
|
@ -431,14 +433,11 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
|||
if( aEvent.IsMotion() || aEvent.IsClick() )
|
||||
{
|
||||
VECTOR2I p = aEvent.Position();
|
||||
|
||||
startItem = pickSingleItem( p );
|
||||
|
||||
bool snapEnabled = !aEvent.Modifier(MD_SHIFT);
|
||||
|
||||
m_router->EnableSnapping ( snapEnabled );
|
||||
|
||||
if(!snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) )
|
||||
if( !snapEnabled && startItem && !startItem->Layers().Overlaps( tl ) )
|
||||
startItem = NULL;
|
||||
|
||||
if( startItem && startItem->Net() >= 0 )
|
||||
|
@ -446,10 +445,13 @@ void ROUTER_TOOL::updateStartItem( TOOL_EVENT& aEvent )
|
|||
bool dummy;
|
||||
VECTOR2I psnap = m_router->SnapToItem( startItem, p, dummy );
|
||||
|
||||
if (snapEnabled) {
|
||||
if( snapEnabled )
|
||||
{
|
||||
m_startSnapPoint = psnap;
|
||||
ctls->ForceCursorPosition( true, psnap );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_startSnapPoint = cp;
|
||||
ctls->ForceCursorPosition( false );
|
||||
}
|
||||
|
@ -514,8 +516,7 @@ void ROUTER_TOOL::updateEndItem( TOOL_EVENT& aEvent )
|
|||
}
|
||||
|
||||
if( m_endItem )
|
||||
TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() %
|
||||
m_endItem->Layers().Start() );
|
||||
TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() % m_endItem->Layers().Start() );
|
||||
}
|
||||
|
||||
|
||||
|
@ -573,7 +574,8 @@ void ROUTER_TOOL::performRouting()
|
|||
break;
|
||||
|
||||
m_router->Move( m_endSnapPoint, m_endItem );
|
||||
} else if( evt->IsAction( &ACT_PlaceThroughVia ) )
|
||||
}
|
||||
else if( evt->IsAction( &ACT_PlaceThroughVia ) )
|
||||
{
|
||||
m_router->ToggleViaPlacement();
|
||||
frame->SetTopLayer( m_router->GetCurrentLayer() );
|
||||
|
@ -636,7 +638,8 @@ int ROUTER_TOOL::Main( TOOL_EVENT& aEvent )
|
|||
// Deselect all items
|
||||
m_toolMgr->RunAction( COMMON_ACTIONS::selectionClear );
|
||||
|
||||
getEditFrame<PCB_EDIT_FRAME>()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL, _( "Interactive Router" ) );
|
||||
getEditFrame<PCB_EDIT_FRAME>()->SetToolID( ID_TRACK_BUTT, wxCURSOR_PENCIL,
|
||||
_( "Interactive Router" ) );
|
||||
|
||||
ctls->SetSnapping( true );
|
||||
ctls->ShowCursor( true );
|
||||
|
@ -700,7 +703,7 @@ void ROUTER_TOOL::performDragging()
|
|||
|
||||
bool dragStarted = m_router->StartDragging( m_startSnapPoint, m_startItem );
|
||||
|
||||
if(!dragStarted)
|
||||
if( !dragStarted )
|
||||
return;
|
||||
|
||||
if( m_startItem && m_startItem->Net() >= 0 )
|
||||
|
@ -725,12 +728,11 @@ void ROUTER_TOOL::performDragging()
|
|||
}
|
||||
else if( evt->IsClick( BUT_LEFT ) )
|
||||
{
|
||||
|
||||
if( m_router->FixRoute( m_endSnapPoint, m_endItem ) )
|
||||
break;
|
||||
|
||||
}
|
||||
handleCommonEvents(*evt);
|
||||
|
||||
handleCommonEvents( *evt );
|
||||
}
|
||||
|
||||
if( m_router->RoutingInProgress() )
|
||||
|
|
|
@ -49,7 +49,6 @@ public:
|
|||
int Main( TOOL_EVENT& aEvent );
|
||||
|
||||
private:
|
||||
|
||||
PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 );
|
||||
|
||||
int getDefaultWidth( int aNetCode );
|
||||
|
@ -57,7 +56,7 @@ private:
|
|||
void performRouting();
|
||||
void performDragging();
|
||||
|
||||
void highlightNet( bool enabled, int netcode = -1 );
|
||||
void highlightNet( bool aEnabled, int aNetcode = -1 );
|
||||
|
||||
void updateStartItem( TOOL_EVENT& aEvent );
|
||||
void updateEndItem( TOOL_EVENT& aEvent );
|
||||
|
@ -78,7 +77,6 @@ private:
|
|||
PNS_ITEM* m_endItem;
|
||||
VECTOR2I m_endSnapPoint;
|
||||
|
||||
|
||||
CONTEXT_MENU* m_menu;
|
||||
|
||||
///> Flag marking that the router's world needs syncing.
|
||||
|
|
|
@ -24,23 +24,28 @@
|
|||
|
||||
TIME_LIMIT::TIME_LIMIT( int aMilliseconds ) :
|
||||
m_limitMs( aMilliseconds )
|
||||
{
|
||||
Restart();
|
||||
};
|
||||
{
|
||||
Restart();
|
||||
}
|
||||
|
||||
|
||||
TIME_LIMIT::~TIME_LIMIT()
|
||||
{}
|
||||
|
||||
TIME_LIMIT::~TIME_LIMIT () {}
|
||||
|
||||
bool TIME_LIMIT::Expired() const
|
||||
{
|
||||
return ( wxGetLocalTimeMillis().GetValue() - m_startTics ) >= m_limitMs;
|
||||
}
|
||||
|
||||
|
||||
void TIME_LIMIT::Restart()
|
||||
{
|
||||
m_startTics = wxGetLocalTimeMillis().GetValue();
|
||||
}
|
||||
|
||||
void TIME_LIMIT::Set ( int aMilliseconds )
|
||||
|
||||
void TIME_LIMIT::Set( int aMilliseconds )
|
||||
{
|
||||
m_limitMs = aMilliseconds;
|
||||
}
|
||||
|
|
|
@ -23,22 +23,20 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
class TIME_LIMIT {
|
||||
|
||||
class TIME_LIMIT
|
||||
{
|
||||
public:
|
||||
TIME_LIMIT( int aMilliseconds = 0);
|
||||
~TIME_LIMIT ();
|
||||
TIME_LIMIT( int aMilliseconds = 0 );
|
||||
~TIME_LIMIT();
|
||||
|
||||
bool Expired() const;
|
||||
void Restart();
|
||||
|
||||
void Set ( int aMilliseconds );
|
||||
void Set( int aMilliseconds );
|
||||
|
||||
private:
|
||||
|
||||
int m_limitMs;
|
||||
int64_t m_startTics;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -25,10 +25,10 @@
|
|||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
static inline void _trace_print( const char* aFuncName, int level, const std::string& aMsg )
|
||||
static inline void _trace_print( const char* aFuncName, int aLevel, const std::string& aMsg )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
std::cerr << "trace[" << level << "]: " << aFuncName << ": " << aMsg << std::endl;
|
||||
std::cerr << "trace[" << aLevel << "]: " << aFuncName << ": " << aMsg << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue