Initial version of the P&S router. Buggy and crappy.

parent 74f42a62
include_directories(BEFORE ${INC_BEFORE})
include_directories(
./
../
../../include
../../pcbnew
../../polygon
${INC_AFTER}
)
set(PCBNEW_PNS_SRCS
direction.h
pns_via.h
pns_routing_settings.h
pns_shove.cpp
pns_line.cpp
pns_utils.h
pns_layerset.h
trace.h
pns_line.h
pns_walkaround.cpp
pns_node.h
pns_line_placer.cpp
pns_utils.cpp
pns_solid.h
pns_item.cpp
pns_via.cpp
pns_node.cpp
pns_solid.cpp
pns_line_placer.h
pns_optimizer.h
pns_walkaround.h
pns_shove.h
pns_router.h
pns_router.cpp
pns_index.h
pns_item.h
pns_optimizer.cpp
pns_joint.h
pns_segment.h
pns_itemset.h
pns_itemset.cpp
router_tool.cpp
router_tool.h
router_preview_item.cpp
router_preview_item.h
)
add_library(pnsrouter STATIC ${PCBNEW_PNS_SRCS})
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __DIRECTION_H
#define __DIRECTION_H
#include <geometry/seg.h>
#include <geometry/shape_line_chain.h>
/**
* Class DIRECTION_45.
* Represents route directions & corner angles in a 45-degree metric.
*/
class DIRECTION_45
{
public:
/**
* Enum Directions
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
*/
enum Directions {
N = 0,
NE = 1,
E = 2,
SE = 3,
S = 4,
SW = 5,
W = 6,
NW = 7,
UNDEFINED = -1
};
/**
* Enum AngleType
* Represents kind of angle formed by vectors heading in two DIRECTION_45s.
*/
enum AngleType {
ANG_OBTUSE = 0x1,
ANG_RIGHT = 0x2,
ANG_ACUTE = 0x4,
ANG_STRAIGHT = 0x8,
ANG_HALF_FULL = 0x10,
ANG_UNDEFINED = 0x20
};
DIRECTION_45(Directions aDir = UNDEFINED): m_dir(aDir) {};
/**
* Constructor
* @param aVec vector, whose direction will be translated into a DIRECTION_45.
*/
DIRECTION_45(const VECTOR2I& aVec)
{
construct(aVec);
}
/**
* Constructor
* @param aSeg segment, whose direction will be translated into a DIRECTION_45.
*/
DIRECTION_45(const SEG& aSeg)
{
construct( aSeg.b - aSeg.a );
}
/**
* Function Format()
* Formats the direction in a human readable word.
* @return name of the direction
*/
const std::string Format() const
{
switch(m_dir)
{
case N : return "north";
case NE : return "north-east";
case E : return "east";
case SE : return "south-east";
case S : return "south";
case SW : return "south-west";
case W : return "west";
case NW : return "north-west";
case UNDEFINED : return "undefined";
default: return "<Error>";
}
}
/**
* Function Opposite()
* Returns a direction opposite (180 degree) to (this)
* @return opposite direction
*/
DIRECTION_45 Opposite() const
{
if(m_dir == UNDEFINED)
return UNDEFINED;
const Directions OppositeMap[] = { S, SW, W, NW, N, NE, E, SE } ;
return OppositeMap[m_dir];
}
/**
* Function Angle()
* Returns the type of angle between directions (this) and aOther.
* @param aOther direction to compare angle with
*/
AngleType Angle(const DIRECTION_45& aOther) const
{
if(m_dir == UNDEFINED || aOther.m_dir == UNDEFINED)
return ANG_UNDEFINED;
int d = std::abs(m_dir - aOther.m_dir);
if(d == 1 || d == 7)
return ANG_OBTUSE;
else if(d == 2 || d == 6)
return ANG_RIGHT;
else if(d == 3 || d == 5)
return ANG_ACUTE;
else if(d == 4)
return ANG_HALF_FULL;
else
return ANG_STRAIGHT;
}
/**
* Function IsObtuse()
* @return true, when (this) forms an obtuse angle with aOther
*/
bool IsObtuse(const DIRECTION_45& aOther) const
{
return Angle(aOther) == ANG_OBTUSE;
}
/**
* Function IsDiagonal()
* Returns true if the direction is diagonal (e.g. North-West, South-East, etc)
* @return true, when diagonal.
*/
bool IsDiagonal() const
{
return (m_dir % 2) == 1;
}
/**
* Function BuildInitialTrace()
*
* Builds a 2-segment line chain between points aP0 and aP1 and following 45-degree routing
* regime. If aStartDiagonal is true, the trace starts with a diagonal segment.
* @param aP0 starting point
* @param aP1 ending point
* @param aStartDiagonal whether the first segment has to be diagonal
* @return the trace
*/
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I& aP0, const VECTOR2I &aP1, bool aStartDiagonal = false) const
{
int w = abs(aP1.x - aP0.x);
int h = abs(aP1.y - aP0.y);
int sw = sign(aP1.x - aP0.x);
int sh = sign(aP1.y - aP0.y);
VECTOR2I mp0, mp1;
// we are more horizontal than vertical?
if(w > h)
{
mp0 = VECTOR2I((w - h) * sw, 0); // direction: E
mp1 = VECTOR2I(h * sw, h * sh); // direction: NE
} else {
mp0 = VECTOR2I(0, sh * (h - w)); // direction: N
mp1 = VECTOR2I(sw * w, sh * w); // direction: NE
}
bool start_diagonal;
if(m_dir == UNDEFINED)
start_diagonal = aStartDiagonal;
else
start_diagonal = IsDiagonal();
SHAPE_LINE_CHAIN pl;
pl.Append(aP0);
if (start_diagonal)
pl.Append(aP0 + mp1);
else
pl.Append(aP0 + mp0);
pl.Append(aP1);
pl.Simplify();
return pl;
};
bool operator==(const DIRECTION_45& aOther) const
{
return aOther.m_dir == m_dir;
}
bool operator!=(const DIRECTION_45& aOther) const
{
return aOther.m_dir != m_dir;
}
const DIRECTION_45 Right() const
{
DIRECTION_45 r;
r.m_dir = (Directions) (m_dir + 1);
if(r.m_dir == NW)
r.m_dir = N;
return r;
}
private:
template <typename T> int sign(T val) const {
return (T(0) < val) - (val < T(0));
}
/**
* Function construct()
* Calculates the direction from a vector. If the vector's angle is not a multiple of 45
* degrees, the direction is rounded to the nearest octant.
* @param aVec our vector
*/
void construct(const VECTOR2I& aVec)
{
m_dir = UNDEFINED;
if(aVec.x == 0 && aVec.y == 0)
return;
double mag = 360.0 - (180.0 / M_PI * atan2 ((double) aVec.y, (double) aVec.x )) + 90.0;
if (mag >= 360.0)
mag -= 360.0;
if(mag < 0.0)
mag += 360.0;
m_dir = (Directions) ((mag + 22.5) / 45.0);
if(m_dir >= 8)
m_dir = (Directions) (m_dir - 8);
if(m_dir < 0)
m_dir = (Directions) (m_dir + 8);
return ;
if(aVec.y < 0)
{
if(aVec.x > 0)
m_dir = NE;
else if(aVec.x < 0)
m_dir = NW;
else
m_dir = N;
}
else if(aVec.y == 0)
{
if(aVec.x > 0)
m_dir = E;
else
m_dir = W;
}
else // aVec.y>0
{
if(aVec.x > 0)
m_dir = SE;
else if(aVec.x < 0)
m_dir = SW;
else
m_dir = S;
}
}
Directions m_dir; ///> our actual direction
};
#endif // __DIRECTION_H
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_INDEX_H
#define __PNS_INDEX_H
#include <boost/foreach.hpp>
#include <boost/range/adaptor/map.hpp>
#include <list>
#include <geometry/shape_index.h>
#include "pns_item.h"
/**
* Class PNS_INDEX
*
* Custom spatial index, holding our board items and allowing for very fast searches. Items
* are assigned to separate R-Tree subundices 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;
PNS_INDEX();
~PNS_INDEX();
void Add( PNS_ITEM *aItem );
void Remove ( PNS_ITEM *aItem );
void Replace ( PNS_ITEM *aOldItem, PNS_ITEM *aNewItem );
template<class Visitor>
int Query( const PNS_ITEM *aItem, int aMinDistance, Visitor &v);
template<class Visitor>
int Query( const SHAPE *aShape, int aMinDistance, Visitor &v);
void Clear();
NetItemsList* GetItemsForNet ( int aNet ) ;
ItemSet::iterator begin() { return m_allItems.begin(); }
ItemSet::iterator end() { return m_allItems.end(); }
bool Contains ( PNS_ITEM *aItem ) const {
return m_allItems.find(aItem) != m_allItems.end();
}
int Size() const { return m_allItems.size(); }
private:
static const int MaxSubIndices = 64;
static const int SI_Multilayer = 2;
static const int SI_SegDiagonal = 0;
static const int SI_SegStraight = 1;
static const int SI_Traces = 3;
static const int SI_PadsTop = 0;
static const int SI_PadsBottom = 1;
template<class Visitor>
int querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v);
ItemShapeIndex *getSubindex( const PNS_ITEM *aItem );
ItemShapeIndex *m_subIndices[ MaxSubIndices ];
std::map<int, NetItemsList> m_netMap;
ItemSet m_allItems;
};
PNS_INDEX::PNS_INDEX()
{
memset(m_subIndices, 0, sizeof(m_subIndices));
}
PNS_INDEX::ItemShapeIndex *PNS_INDEX::getSubindex(const PNS_ITEM *aItem )
{
int idx_n = -1;
const PNS_LAYERSET l = aItem->GetLayers();
switch(aItem->GetKind())
{
case PNS_ITEM::VIA:
idx_n = SI_Multilayer;
break;
case PNS_ITEM::SOLID:
{
if( l.IsMultilayer() )
idx_n = SI_Multilayer;
else if (l.Start() == 0) // fixme: use kicad layer codes
idx_n = SI_PadsTop;
else if (l.Start() == 15)
idx_n = SI_PadsBottom;
break;
}
case PNS_ITEM::SEGMENT:
case PNS_ITEM::LINE:
idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight;
break;
default:
break;
}
assert(idx_n >= 0 && idx_n < MaxSubIndices);
if(!m_subIndices[idx_n])
m_subIndices[idx_n] = new ItemShapeIndex;
return m_subIndices[idx_n];
}
void PNS_INDEX::Add( PNS_ITEM *aItem )
{
ItemShapeIndex *idx = getSubindex(aItem);
idx->Add(aItem);
m_allItems.insert(aItem);
int net = aItem->GetNet();
if(net >= 0)
{
m_netMap[net].push_back(aItem);
}
}
void PNS_INDEX::Remove( PNS_ITEM *aItem )
{
ItemShapeIndex *idx = getSubindex(aItem);
idx->Remove(aItem);
m_allItems.erase (aItem);
int net = aItem->GetNet();
if(net >= 0 && m_netMap.find(net) != m_netMap.end())
m_netMap[net].remove(aItem);
}
void PNS_INDEX::Replace( PNS_ITEM *aOldItem, PNS_ITEM *aNewItem )
{
Remove(aOldItem);
Add(aNewItem);
}
template<class Visitor>
int PNS_INDEX::querySingle( int index, const SHAPE *aShape, int aMinDistance, Visitor &v)
{
if(!m_subIndices[index])
return 0;
return m_subIndices[index] -> Query(aShape, aMinDistance, v, false);
}
template<class Visitor>
int PNS_INDEX::Query( const PNS_ITEM *aItem, int aMinDistance, Visitor &v)
{
const SHAPE *shape = aItem->GetShape();
int total = 0;
total += querySingle(SI_Multilayer, shape, aMinDistance, v);
const PNS_LAYERSET layers = aItem->GetLayers();
if(layers.IsMultilayer())
{
total += querySingle(SI_PadsTop, shape, aMinDistance, v);
total += querySingle(SI_PadsBottom, shape, aMinDistance, v);
for(int i = layers.Start(); i <= layers.End(); ++i )
total += querySingle( SI_Traces + 2 * i + SI_SegStraight, shape, aMinDistance, v);
} else {
int l = layers.Start();
if(l == 0)
total += querySingle(SI_PadsTop, shape, aMinDistance, v);
else if(l == 15)
total += querySingle(SI_PadsBottom, shape, aMinDistance, v);
total += querySingle ( SI_Traces + 2 * l + SI_SegStraight, shape, aMinDistance, v);
}
return total;
}
template<class Visitor>
int PNS_INDEX::Query( const SHAPE *aShape, int aMinDistance, Visitor &v)
{
int total = 0;
for(int i = 0; i < MaxSubIndices; i++)
total += querySingle(i, aShape, aMinDistance, v);
return total;
}
void PNS_INDEX::Clear()
{
for(int i = 0; i < MaxSubIndices; ++i)
{
ItemShapeIndex *idx = m_subIndices[i];
if(idx)
delete idx;
m_subIndices[i] = NULL;
}
}
PNS_INDEX::~PNS_INDEX()
{
Clear();
}
PNS_INDEX::NetItemsList* PNS_INDEX::GetItemsForNet ( int aNet )
{
if(m_netMap.find(aNet) == m_netMap.end())
return NULL;
return &m_netMap[aNet];
}
#endif
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#include "pns_item.h"
#include "pns_line.h"
bool PNS_ITEM::collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
{
// same nets? no collision!
if( m_net == aOther->m_net )
return false;
// check if we are not on completely different layers first
if (!m_layers.Overlaps (aOther->m_layers))
return false;
return GetShape()->Collide ( aOther->GetShape(), aClearance );
// fixme: MTV
}
bool PNS_ITEM::Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const
{
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
return true;
// special case for "head" line with a via attached at the end.
if( aOther->m_kind == LINE )
{
const PNS_LINE *line = static_cast<const PNS_LINE *> (aOther);
if(line -> EndsWithVia())
return collideSimple( &line->GetVia(), aClearance - line->GetWidth() / 2, aNeedMTV, aMTV );
}
return false;
}
const std::string PNS_ITEM::GetKindStr() const
{
switch(m_kind)
{
case LINE: return "line";
case SEGMENT: return "segment";
case VIA: return "via";
case JOINT: return "joint";
case SOLID: return "solid";
default: return "unknown";
}
}
PNS_ITEM::~PNS_ITEM()
{
}
\ No newline at end of file
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_ITEM_H
#define __PNS_ITEM_H
#include <math/vector2d.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include "pns_layerset.h"
class BOARD_ITEM;
class PNS_NODE;
/**
* Class PNS_ITEM
*
* Base class for PNS router board items. Implements the shared properties of all PCB items -
* net, spanned layers, geometric shape & refererence to owning model.
*/
class PNS_ITEM
{
public:
static const int UnusedNet = INT_MAX;
///> Supported item types
enum PnsKind {
SOLID = 1,
LINE = 2,
JOINT = 4,
SEGMENT = 8,
VIA = 16,
ANY = 0xff
};
PNS_ITEM(PnsKind aKind)
{
m_net = UnusedNet;
m_movable = true;
m_kind = aKind;
m_parent = NULL;
m_world = NULL;
m_owner = NULL;
}
PNS_ITEM( const PNS_ITEM& aOther )
{
m_layers = aOther.m_layers;
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_kind = aOther.m_kind;
m_world = aOther.m_world;
m_parent = aOther.m_parent;
m_owner = NULL;
}
virtual ~PNS_ITEM();
virtual PNS_ITEM *Clone() const = 0;
///> Returns a convex polygon "hull" of a the item, that is used as the walkaround
/// path.
/// aClearance defines how far from the body of the item the hull should be,
/// aWalkaroundThickness is the width of the line that walks around this hull.
virtual const SHAPE_LINE_CHAIN Hull(int aClearance = 0, int aWalkaroundThickness = 0) const
{
return SHAPE_LINE_CHAIN();
};
PnsKind GetKind() const { return m_kind; }
bool OfKind( int aKind ) const { return (aKind & m_kind) != 0; }
const std::string GetKindStr() const;
///> Gets/Sets the corresponding parent object in the host application's model (pcbnew)
void SetParent(BOARD_ITEM *aParent) { m_parent = aParent; }
BOARD_ITEM *GetParent() const { return m_parent; }
///> Net accessors
int GetNet() const { return m_net; }
void SetNet(int aNet) { m_net = aNet; }
///> Layers accessors
const PNS_LAYERSET& GetLayers() const { return m_layers; }
void SetLayers ( const PNS_LAYERSET& aLayers ) { m_layers = aLayers; }
void SetLayer ( int aLayer ) { m_layers = PNS_LAYERSET (aLayer, aLayer); }
///> Ownership management. An item can belong to a single PNS_NODE or stay unowned.
void SetOwner (PNS_NODE *aOwner) { m_owner = aOwner; }
bool BelongsTo (PNS_NODE *aNode) const { return m_owner == aNode; }
PNS_NODE *GetOwner() const { return m_owner; }
///> Sets the world that is used for collision resolution.
void SetWorld (PNS_NODE *aWorld) { m_world = aWorld; }
PNS_NODE *GetWorld() const { return m_world; }
///> Collision function. Checks if the item aOther is closer to us than
/// aClearance and returns true if so. It can also calculate a minimum translation vector that resolves the
/// collision if needed.
virtual bool Collide( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const;
///> A shortcut without MTV calculation
bool Collide( const PNS_ITEM *aOther, int aClearance ) const
{
VECTOR2I dummy;
return Collide(aOther, aClearance, false, dummy);
}
///> Returns the geometric shape of the item
virtual const SHAPE* GetShape() const {
return NULL;
}
private:
bool collideSimple ( const PNS_ITEM *aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) const;
protected:
PnsKind m_kind;
BOARD_ITEM *m_parent;
PNS_NODE *m_world;
PNS_NODE *m_owner;
PNS_LAYERSET m_layers;
bool m_movable;
int m_net;
};
#endif // __PNS_ITEM_H
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#include <boost/foreach.hpp>
#include "pns_itemset.h"
PNS_ITEMSET::PNS_ITEMSET()
{
}
PNS_ITEMSET::~PNS_ITEMSET()
{
}
PNS_ITEMSET& PNS_ITEMSET::FilterLayers ( int aStart, int aEnd )
{
ItemVector newItems;
PNS_LAYERSET l;
if(aEnd < 0)
l = PNS_LAYERSET(aStart);
else
l = PNS_LAYERSET(aStart, aEnd);
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetLayers(). Overlaps ( l ))
newItems.push_back(item);
m_items = newItems;
return *this;
}
PNS_ITEMSET& PNS_ITEMSET::FilterKinds ( int aKindMask )
{
ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetKind() & aKindMask )
newItems.push_back(item);
m_items = newItems;
return *this;
}
PNS_ITEMSET& PNS_ITEMSET::FilterNet ( int aNet )
{
ItemVector newItems;
BOOST_FOREACH( PNS_ITEM *item, m_items )
if(item->GetNet() == aNet)
newItems.push_back(item);
m_items = newItems;
return *this;
}
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_ITEMSET_H
#define __PNS_ITEMSET_H
#include <vector>
#include "pns_item.h"
/**
* Class PNS_ITEMSET
*
* Holds a list of board items, that can be filtered against net, kinds, layers, etc.
**/
class PNS_ITEMSET
{
public:
typedef std::vector<PNS_ITEM *> ItemVector;
PNS_ITEMSET();
~PNS_ITEMSET();
ItemVector& Items() { return m_items; }
PNS_ITEMSET& FilterLayers ( int aStart, int aEnd = -1 );
PNS_ITEMSET& FilterKinds ( int aKindMask );
PNS_ITEMSET& FilterNet ( int aNet );
int Size() { return m_items.size(); }
void Add(PNS_ITEM *item)
{
m_items.push_back(item);
}
PNS_ITEM *Get( int index ) const { return m_items[index]; }
private:
ItemVector m_items;
};
#endif
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_JOINT_H
#define __PNS_JOINT_H
#include <vector>
#include <boost/functional/hash.hpp>
#include <math/vector2d.h>
#include "pns_item.h"
#include "pns_segment.h"
/**
* Class PNS_JOINT
*
* Represents a 2D point on a given set of layers and belonging to a certain net,
* that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between the items.
**/
class PNS_JOINT : public PNS_ITEM
{
public:
typedef std::vector<PNS_ITEM *> LinkedItems;
///> joints are hashed by their position, layers and net. Linked items are, obviously, not hashed
struct HashTag {
VECTOR2I pos;
int net;
};
PNS_JOINT():
PNS_ITEM(JOINT) {}
PNS_JOINT(const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet = -1):
PNS_ITEM(JOINT)
{
m_tag.pos = aPos;
m_tag.net = aNet;
m_layers = aLayers;
}
PNS_JOINT(const PNS_JOINT& b):
PNS_ITEM(JOINT)
{
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;
}
PNS_ITEM *Clone() const
{
assert(false);
return NULL;
}
///> returns true if the joint is a trivial line corner, connecting two segments of the same net, on the same layer.
bool IsLineCorner() const
{
if(m_linkedItems.size() != 2)
return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || m_linkedItems[1]->GetKind() != SEGMENT )
return false;
PNS_SEGMENT *seg1 = static_cast<PNS_SEGMENT *> (m_linkedItems[0]);
PNS_SEGMENT *seg2 = static_cast<PNS_SEGMENT *> (m_linkedItems[1]);
// joints between segments of different widths are not trivial.
return (seg1->GetWidth() == seg2->GetWidth());
}
///> Links the joint to a given board item (when it's added to the PNS_NODE)
void Link ( PNS_ITEM *aItem )
{
LinkedItems::iterator f = std::find(m_linkedItems.begin(), m_linkedItems.end(), aItem);
if(f != m_linkedItems.end())
return;
m_linkedItems.push_back(aItem);
}
///> Unlinks a given board item from the joint (upon its removal from a PNS_NODE)
///> 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);
if(f != m_linkedItems.end())
m_linkedItems.erase(f);
return (m_linkedItems.size() == 0);
}
///> For trivial joints, returns the segment adjacent to (aCurrent). For non-trival ones, returns
///> NULL, indicating the end of line.
PNS_SEGMENT* NextSegment( PNS_SEGMENT* aCurrent) const
{
if(!IsLineCorner())
return NULL;
return static_cast<PNS_SEGMENT *> (m_linkedItems [ m_linkedItems[0] == aCurrent ? 1 : 0 ] );
}
/// trivial accessors
const HashTag& GetTag() const { return m_tag; }
const VECTOR2I& GetPos() const { return m_tag.pos; }
int GetNet() const { return m_tag.net; }
LinkedItems & GetLinkList() { return m_linkedItems; };
///> Returns the number of linked items of types listed in aMask.
int LinkCount( int aMask = -1 ) const
{
int n = 0;
for(LinkedItems::const_iterator i = m_linkedItems.begin(); i!= m_linkedItems.end(); ++i)
if( (*i)->GetKind() & aMask )
n++;
return n;
}
void Dump() const;
bool operator==(const PNS_JOINT& rhs) const
{
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net;
}
void Merge( const PNS_JOINT& aJoint )
{
if(!Overlaps(aJoint))
return;
m_layers.Merge (aJoint.m_layers);
// fixme: duplicate links (?)
for(LinkedItems::const_iterator i =aJoint.m_linkedItems.begin(); i!=aJoint.m_linkedItems.end();++i)
m_linkedItems.push_back(*i);
}
bool Overlaps(const PNS_JOINT& rhs) const
{
return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net && m_layers.Overlaps(rhs.m_layers);
}
private:
///> hash tag for unordered_multimap
HashTag m_tag;
///> list of items linked to this joint
LinkedItems m_linkedItems;
};
// hash function & comparison operator for boost::unordered_map<>
inline bool operator==(PNS_JOINT::HashTag const& p1, PNS_JOINT::HashTag const& p2)
{
return p1.pos == p2.pos && p1.net == p2.net;
}
inline std::size_t hash_value(PNS_JOINT::HashTag const& p)
{
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);
return seed;
}
#endif // __PNS_JOINT_H
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_LAYERSET_H
#define __PNS_LAYERSET_H
#include <algorithm>
/**
* Class PNS_LAYERSET
*
* Represents a contiguous set of PCB layers.
*/
class PNS_LAYERSET
{
public:
PNS_LAYERSET():
m_start(-1),
m_end(-1)
{};
PNS_LAYERSET (int aStart, int aEnd)
{
if(aStart > aEnd)
std::swap(aStart, aEnd);
m_start = aStart;
m_end = aEnd;
}
PNS_LAYERSET (int aLayer)
{
m_start = m_end = aLayer;
}
PNS_LAYERSET(const PNS_LAYERSET &b) :
m_start(b.m_start),
m_end (b.m_end)
{}
~PNS_LAYERSET () {};
const PNS_LAYERSET& operator= ( const PNS_LAYERSET& b)
{
m_start = b.m_start;
m_end = b.m_end;
return *this;
}
bool Overlaps ( const PNS_LAYERSET& aOther ) const
{
return m_end >= aOther.m_start && m_start <= aOther.m_end;
}
bool Overlaps ( const int aLayer ) const
{
return aLayer >= m_start && aLayer <= m_end;
}
bool IsMultilayer ( ) const
{
return m_start != m_end;
}
int Start() const {
return m_start;
}
int End() const {
return m_end;
}
void Merge ( const PNS_LAYERSET& aOther )
{
if(m_start < 0 || m_end < 0)
{
m_start = aOther.m_start;
m_end = aOther.m_end;
return;
}
if(aOther.m_start < m_start)
m_start = aOther.m_start;
if(aOther.m_end > m_end)
m_end = aOther.m_end;
}
///> Shortcut for comparisons/overlap tests
static PNS_LAYERSET All()
{
return PNS_LAYERSET(0, 256);
}
private:
int m_start;
int m_end;
};
#endif // __PNS_LAYERSET_H
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_LINE_H
#define __PNS_LINE_H
#include <math/vector2d.h>
#include <geometry/seg.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include "direction.h"
#include "pns_item.h"
#include "pns_via.h"
class PNS_NODE;
class PNS_SEGMENT;
class PNS_VIA;
/**
* Class PNS_LINE
*
* Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,
* junctions between multiple traces or two traces different widths and combinations of these).
* PNS_LINEs are NOT stored in the model (PNS_NODE) - instead, they are assembled on-the-fly, based on
* a via/pad/segment that belongs/begins them.
*
* PNS_LINEs can be either loose (consisting of segments that do not belong to any PNS_NODE) or owned (with segments
* taken from a PNS_NODE) - these are returned by PNS_NODE::AssembleLine and friends.
*
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via dragging/force propagation stuff.
*/
class PNS_LINE : public PNS_ITEM
{
public:
typedef std::vector<PNS_SEGMENT *> LinkedSegments;
PNS_LINE ():
PNS_ITEM(LINE)
{
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
};
PNS_LINE (int aLayer, int aWidth, const SHAPE_LINE_CHAIN& aLine) :
PNS_ITEM(LINE)
{
m_line = aLine;
m_width = aWidth;
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
SetLayer(aLayer);
}
PNS_LINE(const PNS_LINE& aOther) :
PNS_ITEM(aOther),
m_line(aOther.m_line),
m_width(aOther.m_width)
{
m_net = aOther.m_net;
m_movable = aOther.m_movable;
m_world = aOther.m_world;
m_layers = aOther.m_layers;
m_segmentRefs = NULL;
m_via = aOther.m_via;
m_hasVia = aOther.m_hasVia;
m_affectedRangeStart = -1;
}
/**
* Constructor
* copies properties (net, layers from a base line), and replaces the shape
* by aLine
**/
PNS_LINE(const PNS_LINE& aBase, const SHAPE_LINE_CHAIN& aLine) :
PNS_ITEM(aBase),
m_line(aLine),
m_width(aBase.m_width)
{
m_net = aBase.m_net;
m_layers = aBase.m_layers;
m_segmentRefs = NULL;
m_hasVia = false;
m_affectedRangeStart = -1;
}
~PNS_LINE ()
{
if(m_segmentRefs)
delete m_segmentRefs;
};
virtual PNS_LINE *Clone() const ;
///> clones the line without cloning the shape (just the properties - net, width, layers, etc.)
PNS_LINE *CloneProperties() const ;
int GetLayer() const { return GetLayers().Start(); }
///> Geometry accessors
void SetShape(const SHAPE_LINE_CHAIN& aLine) { m_line = aLine; }
const SHAPE* GetShape() const { return &m_line; }
SHAPE_LINE_CHAIN& GetLine() { return m_line; }
const SHAPE_LINE_CHAIN& GetCLine() const { return m_line; }
///> Width accessors
void SetWidth( int aWidth ) { m_width = aWidth; }
int GetWidth () const { return m_width; }
///> Links a segment from a PNS_NODE to this line, making it owned by the node
void LinkSegment(PNS_SEGMENT *aSeg)
{
if(!m_segmentRefs)
m_segmentRefs = new std::vector<PNS_SEGMENT *> ();
m_segmentRefs->push_back(aSeg);
}
///> Returns a list of segments from the owning node that constitute this line (or NULL if
///> the line is loose)
LinkedSegments* GetLinkedSegments()
{
return m_segmentRefs;
}
bool ContainsSegment (PNS_SEGMENT *aSeg) const
{
if (!m_segmentRefs)
return false;
return std::find( m_segmentRefs->begin(), m_segmentRefs->end(), aSeg) != m_segmentRefs->end();
}
///> Returns this line, but clipped to the nearest obstacle along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE *aNode ) const;
///> DEPRECATED optimization functions (moved to PNS_OPTIMIZER)
bool MergeObtuseSegments();
bool MergeSegments();
///> Returns the number of corners of angles specified by mask aAngles.
int CountCorners(int aAngles);
///> Calculates a line thightly wrapping a convex hull of an obstacle object (aObstacle).
///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle
///> aPostPath = past from obstacle till the end
///> aCW = whether to walkaround in clockwise or counter-clockwise direction.
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPrePath,
SHAPE_LINE_CHAIN& aWalkaroundPath,
SHAPE_LINE_CHAIN& aPostPath,
bool aCw ) const;
void NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath,
bool aCw ) const;
bool Walkaround(SHAPE_LINE_CHAIN obstacle, SHAPE_LINE_CHAIN &pre, SHAPE_LINE_CHAIN &walk, SHAPE_LINE_CHAIN &post, bool cw) const;
void Walkaround( const SHAPE_LINE_CHAIN& aObstacle,
SHAPE_LINE_CHAIN& aPath,
bool aCw ) const;
bool Is45Degree();
///> Prints out all linked segments
void ShowLinks();
bool EndsWithVia() const { return m_hasVia; }
void AppendVia ( const PNS_VIA &aVia ) {
m_hasVia = true;
m_via = aVia;
m_via.SetNet ( m_net ) ;
}
void RemoveVia() { m_hasVia = false; }
const PNS_VIA& GetVia() const { return m_via; }
void SetAffectedRange ( int aStart, int aEnd )
{
m_affectedRangeStart = aStart;
m_affectedRangeEnd = aEnd;
}
void ClearAffectedRange ( )
{
m_affectedRangeStart = -1;
}
bool GetAffectedRange ( int& aStart, int& aEnd )
{
if(m_affectedRangeStart >= 0)
{
aStart = m_affectedRangeStart;
aEnd = m_affectedRangeEnd;
return true;
} else {
aStart = 0;
aEnd = m_line.PointCount();
return false;
}
}
private:
bool onEdge(const SHAPE_LINE_CHAIN &obstacle, VECTOR2I p, int& ei, bool& is_vertex) const;
bool walkScan(const SHAPE_LINE_CHAIN &line, const SHAPE_LINE_CHAIN &obstacle, bool reverse, VECTOR2I &ip, int& index_o, int& index_l, bool& is_vertex) const;
///> List of semgments in a PNS_NODE (PNS_ITEM::m_owner) that constitute this line.
LinkedSegments* m_segmentRefs;
///> Shape of the line
SHAPE_LINE_CHAIN m_line;
int m_width;
///> Via at the end and a flag indicating if it's enabled.
PNS_VIA m_via;
bool m_hasVia;
int m_affectedRangeStart;
int m_affectedRangeEnd;
};
#endif // __PNS_LINE_H
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_LINE_PLACER_H
#define __PNS_LINE_PLACER_H
#include <math/vector2d.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include "pns_node.h"
#include "pns_via.h"
#include "pns_line.h"
#include "pns_routing_settings.h"
class PNS_ROUTER;
class PNS_SHOVE;
class PNS_OPTIMIZER;
class PNS_ROUTER_BASE;
/**
* Class PNS_LINE_PLACER
*
* Interactively routes a single track. Runs shove and walkaround algorithms when needed.
*/
class PNS_LINE_PLACER
{
public:
PNS_LINE_PLACER( PNS_NODE *aWorld );
~PNS_LINE_PLACER();
///> Appends a via at the end of currently placed line.
void AddVia ( bool aEnabled, int aDiameter, int aDrill )
{
m_viaDiameter = aDiameter;
m_viaDrill = aDrill;
m_placingVia = aEnabled;
}
///> Starts placement of a line at point aStart.
void StartPlacement(const VECTOR2I& aStart, int aNet, int aWidth, int aLayer);
///> Updates the routed line with a new ending point.
bool Route(const VECTOR2I& aP);
///> Sets initial routing direction/posture
void SetInitialDirection(const DIRECTION_45& aDirection);
void ApplySettings ( const PNS_ROUTING_SETTINGS& aSettings );
///> Returns the "head" of the line being placed, that is the volatile part that has not been settled yet
const PNS_LINE& GetHead() const { return m_head; }
///> Returns the "tail" of the line being placed the part that has been fixed already (follow mouse mode only)
const PNS_LINE& GetTail() const { return m_tail; }
///> Returns the whole routed line
const PNS_LINE GetTrace() const;
///> Returns the current end of the line being placed. It may not be equal to the cursor position due to collisions.
const VECTOR2I& CurrentEnd() const
{
if(m_head.GetCLine().PointCount() > 0)
return m_head.GetCLine().CPoint(-1);
else if(m_tail.GetCLine().PointCount() > 0)
return m_tail.GetCLine().CPoint(-1);
else
return m_p_start;
}
///> Returns all items in the world that have been affected by the routing operation. Used
/// to update data structures of the host application
void GetUpdatedItems( PNS_NODE::ItemVector& aRemoved, PNS_NODE::ItemVector& aAdded);
///> Toggles the current posture (straight/diagonal) of the trace head.
void FlipPosture();
///> Returns the most recent world state
PNS_NODE *GetCurrentNode() const;
private:
static const double m_shoveLengthThreshold = 1.7;
bool handleViaPlacement ( PNS_LINE& aHead );
bool checkObtusity(const SEG& a, const SEG& b) const;
bool handleSelfIntersections();
bool handlePullback();
bool mergeHead();
bool reduceTail(const VECTOR2I& aEnd);
void fixHeadPosture();
bool optimizeTailHeadTransition();
bool routeHead(const VECTOR2I& aP, PNS_LINE& aNewHead, bool aCwWalkaround = true);
void routeStep(const VECTOR2I& aP);
///> routing mode (walkaround, shove, etc.)
PNS_MODE m_mode;
///> follow mouse trail by attaching new segments to the head as the cursor moves
bool m_follow_mouse;
///> mouse smoothing active
bool m_smooth_mouse;
///> mouse smoothing step (in world units)
int m_smoothing_step;
///> current routing direction
DIRECTION_45 m_direction;
///> routing direction for new traces
DIRECTION_45 m_initial_direction;
///> routing "head": volatile part of the track from the previously
/// analyzed point to the current routing destination
PNS_LINE m_head;
///> routing "tail": part of the track that has been already fixed due to collisions with obstacles
PNS_LINE m_tail;
///> current algorithm iteration
int m_iteration;
///> pointer to world to search colliding items
PNS_NODE *m_world;
///> current routing start point (end of tail, beginning of head)
VECTOR2I m_p_start;
///> The shove engine
PNS_SHOVE *m_shove;
///> Current world state
PNS_NODE *m_currentNode;
///> Are we placing a via?
bool m_placingVia;
///> current via diameter
int m_viaDiameter;
///> current via drill
int m_viaDrill;
///> walkaround algorithm iteration limit
int m_walkaroundIterationLimit;
///> smart pads optimizer enabled.
bool m_smartPads;
};
#endif // __PNS_LINE_PLACER_H
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_NODE_H
#define __PNS_NODE_H
#include <vector>
#include <list>
#include <boost/unordered_set.hpp>
#include <boost/unordered_map.hpp>
#include <boost/optional.hpp>
#include <boost/smart_ptr.hpp>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_index.h>
#include "pns_item.h"
#include "pns_joint.h"
#include "pns_itemset.h"
class PNS_SEGMENT;
class PNS_LINE;
class PNS_SOLID;
class PNS_VIA;
class PNS_RATSNEST;
class PNS_INDEX;
using boost::shared_ptr;
class PNS_CLEARANCE_FUNC {
public:
virtual int operator() ( const PNS_ITEM *a , const PNS_ITEM *b) = 0;
};
/**
* Struct PNS_OBSTACLE
*
* Holds an object colliding with another object, along with
* some useful data about the collision.
**/
struct PNS_OBSTACLE
{
///> Item we search collisions with
PNS_ITEM *head;
///> Item found to be colliding with head
PNS_ITEM *item;
///> Hull of the colliding item
SHAPE_LINE_CHAIN hull;
///> First and last intersection point between the head item and the hull of the
//// colliding item
VECTOR2I ip_first, ip_last;
///> ... and the distance thereof
int dist_first, dist_last;
};
/**
* Class PNS_NODE
*
* Keeps the router "world" - i.e. all the tracks, vias, solids in a hierarchical and indexed way.
* Features:
* - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths
* - 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_JOINT> OptJoint;
PNS_NODE ();
~PNS_NODE ();
///> Returns the expected clearance between items a and b.
int GetClearance(const PNS_ITEM *a, const PNS_ITEM *b) const;
///> Returns the pre-set worst case clearance between any pair of items
int GetMaxClearance() const
{
return m_maxClearance;
}
void SetMaxClearance( int aClearance )
{
m_maxClearance = aClearance;
}
void SetClearanceFunctor (PNS_CLEARANCE_FUNC *aFunc)
{
m_clearanceFunctor = aFunc;
}
///> Finds items that collide with aItem and stores collision information in aObstacles.
int QueryColliding( const PNS_ITEM* aItem, Obstacles& aObstacles, int aKindMask = PNS_ITEM::ANY, int aLimitCount = -1);
///> Finds the nearest item that collides with aItem.
OptObstacle NearestObstacle( const PNS_LINE *aItem, int aKindMask = PNS_ITEM::ANY);
///> Checks if the item collides with anything else in the world, and returns it if so.
OptObstacle CheckColliding ( const PNS_ITEM *aItem, int aKindMask = PNS_ITEM::ANY);
///> Checks if two items collide [deprecated].
bool CheckColliding( const PNS_ITEM *aItemA, const PNS_ITEM *aItemB, int aKindMask = PNS_ITEM::ANY);
///> Hit detection
const PNS_ITEMSET HitTest( const VECTOR2I& aPoint );
void Add(PNS_ITEM *aItem);
void Remove(PNS_ITEM *aItem);
void Replace(PNS_ITEM *aOldItem, PNS_ITEM *aNewItem);
///> Creates a lightweight copy ("branch") of self. Note that if there are any branches
/// in use, their parents must NOT be deleted.
PNS_NODE *Branch();
///> Assembles a line connecting two non-trivial joints the segment aSeg belongs to.
PNS_LINE *AssembleLine(PNS_SEGMENT *aSeg, const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint());
///> Dumps the contents and joints structure
void Dump(bool aLong = false);
///> Returns the number of joints
int JointCount() const
{
return m_joints.size();
}
///> Returns the lists of items removed and added in this branch, with respect
///> to the root.
void GetUpdatedItems( ItemVector& aRemoved, ItemVector& aAdded);
///> Copies the changes from a given branch (aNode) to the root. Called on
///> a non-root branch will fail.
void Commit (PNS_NODE *aNode);
///> finds a joint at a given position, layer and nets
const OptJoint FindJoint(const VECTOR2I &aPos, int aLayer, int aNet);
///> finds all linest between a pair of joints. Used by the loop removal engine.
int FindLinesBetweenJoints( PNS_JOINT& a, PNS_JOINT& b, 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 );
///> finds all joints that have an (in)direct connection(s) (i.e. segments/vias) with the joint aJoint.
void FindConnectedJoints( const PNS_JOINT& aJoint, std::vector<PNS_JOINT *> &aConnectedJoints );
///> Destroys all child nodes. Applicable only to the root node.
void KillChildren();
void AllItemsInNet ( int aNet, std::list<PNS_ITEM *>& aItems);
private:
struct obstacleVisitor;
typedef boost::unordered_multimap<PNS_JOINT::HashTag, PNS_JOINT> JointMap;
typedef JointMap::value_type TagJointPair;
/// nodes are not copyable
PNS_NODE( const PNS_NODE& b);
PNS_NODE &operator=(const PNS_NODE& b);
///> tries to find matching joint and creates a new one if not found
PNS_JOINT& touchJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet );
///> touches a joint and links it to an item
void linkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere );
///> unlinks an item from a joint
void unlinkJoint( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, int aNet, PNS_ITEM *aWhere );
///> helpers for adding/removing items
void addSolid( PNS_SOLID *aSeg );
void addSegment( PNS_SEGMENT *aSeg );
void addLine( PNS_LINE *aLine );
void addVia( PNS_VIA *aVia );
void removeSolid( PNS_SOLID *aSeg );
void removeLine( PNS_LINE *aLine );
void removeSegment (PNS_SEGMENT *aSeg );
void removeVia (PNS_VIA *aVia );
void doRemove( PNS_ITEM *aItem );
void unlinkParent ( );
void releaseChildren ();
bool isRoot() const
{
return m_parent == NULL;
}
///> checks if this branch contains an updated version of the item from the root branch.
bool overrides ( PNS_ITEM * aItem ) const
{
return m_override.find(aItem) != m_override.end();
}
///> 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);
///> spatial index of all items
//SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
///> hash table with the joints, linking the items. Joints are hashed by their
///> position, layer set and net.
JointMap m_joints;
///> node this node was branched from
PNS_NODE *m_parent;
///> root node of the whole hierarchy
PNS_NODE *m_root;
///> list of nodes branched from this one
std::vector<PNS_NODE *> m_children;
///> hash of root's items that are more recent in this node
boost::unordered_set<PNS_ITEM *> m_override;
///> worst case item-item clearance
int m_maxClearance;
///> Clearance resolution functor
PNS_CLEARANCE_FUNC *m_clearanceFunctor;
///> Geometric/Net index of the items
PNS_INDEX *m_index;
///> list of currently processed obstacles.
Obstacles m_obstacleList;
};
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* KiRouter - a push-and-(sometimes-)shove PCB router
*
* Copyright (C) 2013 CERN
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.or/licenses/>.
*/
#ifndef __PNS_ROUTER_SETTINGS
#define __PNS_ROUTER_SETTINGS
///> Routing modes
enum PNS_MODE {
RM_Ignore = 0, ///> Ignore collisions
RM_Shove, ///> Only shove
RM_Walkaround, ///> Only walkaround
RM_Smart ///> Guess what's better
};
class PNS_ROUTING_SETTINGS
{
public:
PNS_MODE m_routingMode;
bool m_removeLoops;
bool m_smartPads;
bool m_suggestEnding;
bool m_shoveOnRequest;
bool m_changePostures;
bool m_followMouse;
int m_lineWidth;
int m_viaDiameter;
int m_viaDrill;
int m_preferredLayer;
int m_walkaroundIterationLimit;
int m_shoveIterationLimit;
};
#endif
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