Commit ad1b138f authored by Maciej Suminski's avatar Maciej Suminski

Reformatted PNS code to conform the coding policy.

parent ebf35fd4
......@@ -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) );
PNS_SEGMENT* seg = (PNS_SEGMENT*) item;
std::auto_ptr<PNS_LINE> l( m_world->AssembleLine( seg, &segIndex ) );
if(segIndex != 0)
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;
......@@ -268,34 +279,41 @@ 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,25 +105,25 @@ 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;
PNS_NODE* m_world;
PNS_NODE* m_lastNode;
DragMode m_mode;
PNS_LINE * m_draggedLine;
PNS_VIA * m_draggedVia;
PNS_LINE* m_draggedLine;
PNS_VIA* m_draggedVia;
PNS_LINE m_lastValidDraggedLine;
PNS_SHOVE * m_shove;
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_VIA* m_initialVia;
PNS_ITEMSET m_draggedItems;
};
......
......@@ -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,8 +133,8 @@ 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;
......@@ -149,21 +148,20 @@ private:
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,9 +205,7 @@ 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 );
......@@ -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;
BOOST_FOREACH( PNS_ITEM * item, m_items )
ITEM_VECTOR newItems;
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;
BOOST_FOREACH( PNS_ITEM * item, m_items )
ITEM_VECTOR newItems;
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( LINKED_ITEMS::iterator i = m_linkedItems.begin(); i != m_linkedItems.end(); ++i )
{
for( LinkedItems::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();
for( LINKED_ITEMS::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i )
{
if( (*i)->Kind() & aMask )
n++;
}
return n;
}
......@@ -189,10 +189,12 @@ public:
m_layers.Merge( aJoint.m_layers );
// fixme: duplicate links (?)
for( LinkedItems::const_iterator i = aJoint.m_linkedItems.begin();
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;
}
......
This diff is collapsed.
......@@ -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;
......
This diff is collapsed.
......@@ -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();
/**
......@@ -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,69 +38,76 @@ 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 )
void PNS_LOGGER::Log ( const PNS_ITEM* aItem, int aKind, const std::string aName )
{
m_theLog << "item " << kind << " " << name << " ";
m_theLog << item->Net() << " " << item->Layers().Start() << " " << item->Layers().End() << " " << item->Marker() << " " << item->Rank();
m_theLog << "aItem " << aKind << " " << aName << " ";
m_theLog << aItem->Net() << " " << aItem->Layers().Start() << " " <<
aItem->Layers().End() << " " << aItem->Marker() << " " << aItem->Rank();
switch(item->Kind())
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;
}
......@@ -110,64 +117,74 @@ void PNS_LOGGER::Log ( const PNS_ITEM *item, int kind, const std::string name )
}
}
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 () );
private:
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() );
void dumpShape ( const SHAPE* sh );
private:
void dumpShape ( const SHAPE* aSh );
bool m_groupOpened;
std::stringstream m_theLog;
......
This diff is collapsed.
This diff is collapsed.
......@@ -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,7 +554,7 @@ 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() )
......@@ -582,7 +576,7 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth,
case SH_SEGMENT:
{
const SHAPE_SEGMENT *seg = static_cast<const SHAPE_SEGMENT*> (shape);
const SHAPE_SEGMENT* seg = static_cast<const SHAPE_SEGMENT*> (shape);
const SHAPE_RECT rect = ApproximateSegmentAsRect ( *seg );
return rectBreakouts( aWidth, &rect, aPermitDiagonal );
}
......@@ -599,20 +593,20 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::computeBreakouts( int aWidth,
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() );
......@@ -742,6 +736,7 @@ bool PNS_OPTIMIZER::runSmartPads( PNS_LINE* aLine )
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 );
......@@ -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;
......
This diff is collapsed.
......@@ -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;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment