Commit fd973478 authored by Maciej Suminski's avatar Maciej Suminski

Merged kicad-pns-tom.

parents 9ec4520c 979f549e
So, finally we've got an integrated interactive, push-and-sometimes-shove router, although with a very limited user interface:
- Edit->Interactive router launches the tool,
- while routing: 'V' key places a via,
- '+' and '-' keys cycle through available layers,
- '/' key switches track posture.
Via/track dimensions are taken from the netclasses.
There are no other options available for the time being - promise to add them soon :)
Tom
\ No newline at end of file
......@@ -1287,7 +1287,7 @@ int RTREE_QUAL::PickBranch( Rect* a_rect, Node* a_node )
ELEMTYPEREAL bestIncr = (ELEMTYPEREAL) -1;
ELEMTYPEREAL area;
ELEMTYPEREAL bestArea;
int best;
int best = 0;
Rect tempRect;
for( int index = 0; index < a_node->m_count; ++index )
......@@ -1480,7 +1480,7 @@ void RTREE_QUAL::ChoosePartition( PartitionVars* a_parVars, int a_minFill )
ASSERT( a_parVars );
ELEMTYPEREAL biggestDiff;
int group, chosen, betterGroup;
int group, chosen = 0, betterGroup = 0;
InitParVars( a_parVars, a_parVars->m_branchCount, a_minFill );
PickSeeds( a_parVars );
......@@ -1603,7 +1603,7 @@ void RTREE_QUAL::InitParVars( PartitionVars* a_parVars, int a_maxRects, int a_mi
RTREE_TEMPLATE
void RTREE_QUAL::PickSeeds( PartitionVars* a_parVars )
{
int seed0, seed1;
int seed0 = 0, seed1 = 0;
ELEMTYPEREAL worst, waste;
ELEMTYPEREAL area[MAXNODES + 1];
......
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file profile.h:
* @brief Simple profiling functions for measuring code execution time.
*/
#ifndef __TPROFILE_H
#define __TPROFILE_H
#include <sys/time.h>
#include <stdint.h>
/**
* Function rdtsc
* Returns processor's time-stamp counter. Main purpose is precise time measuring of code
* execution time.
* @return unsigned long long - Value of time-stamp counter.
*/
#if defined(__i386__)
static __inline__ unsigned long long rdtsc()
{
unsigned long long int x;
__asm__ volatile ( ".byte 0x0f, 0x31" : "=A" ( x ) );
return x;
}
#elif defined(__x86_64__)
static __inline__ unsigned long long rdtsc()
{
unsigned hi, lo;
__asm__ __volatile__ ( "rdtsc" : "=a" ( lo ), "=d" ( hi ) );
return ( (unsigned long long) lo ) | ( ( (unsigned long long) hi ) << 32 );
}
#elif defined(__powerpc__)
static __inline__ unsigned long long rdtsc()
{
unsigned long long int result = 0;
unsigned long int upper, lower, tmp;
__asm__ volatile (
"0: \n"
"\tmftbu %0 \n"
"\tmftb %1 \n"
"\tmftbu %2 \n"
"\tcmpw %2,%0 \n"
"\tbne 0b \n"
: "=r" ( upper ), "=r" ( lower ), "=r" ( tmp )
);
result = upper;
result = result << 32;
result = result | lower;
return result;
}
#endif /* __powerpc__ */
// Fixme: OS X version
/**
* Function get_tics
* Returns the number of microseconds that have elapsed since the system was started.
* @return uint64_t Number of microseconds.
*/
static inline uint64_t get_tics()
{
struct timeval tv;
gettimeofday( &tv, NULL );
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
/**
* Structure for storing data related to profiling counters.
*/
struct prof_counter
{
uint64_t value; /// Stored timer value
bool use_rdtsc; /// Method of time measuring (rdtsc or tics)
};
/**
* Function prof_start
* Begins code execution time counting for a given profiling counter.
* @param cnt is the counter which should be started.
* @param use_rdtsc tells if processor's time-stamp counter should be used for time counting.
* Otherwise is system tics method will be used. IMPORTANT: time-stamp counter should not
* be used on multicore machines executing threaded code.
*/
static inline void prof_start( prof_counter* cnt, bool use_rdtsc )
{
cnt->use_rdtsc = use_rdtsc;
if( use_rdtsc )
{
cnt->value = rdtsc();
}
else
{
cnt->value = get_tics();
}
}
/**
* Function prof_stop
* Ends code execution time counting for a given profiling counter.
* @param cnt is the counter which should be stopped.
*/
static inline void prof_end( prof_counter* cnt )
{
if( cnt->use_rdtsc )
cnt->value = rdtsc() - cnt->value;
else
cnt->value = get_tics() - cnt->value;
}
#endif
#ifndef __TOOL_ACTION_H
#define __TOOL_ACTION_H
#include <string>
#include <wx/wx.h>
#include <tool/tool_base.h>
///> Scope of tool actions
enum TOOL_ActionScope {
SCOPE_CONTEXT = 1, ///> Action belongs to a particular tool (i.e. a part of a pop-up menu)
SCOPE_GLOBAL ///> Global action (toolbar/main menu event, global shortcut)
};
// TOOL_ACTION - represents a single action. For instance:
// - changing layer to top by pressing PgUp
// - running the DRC from the menu
// and so on, and so forth....
class TOOL_ACTION
{
public:
TOOL_ACTION
(
const std::string& name,
TOOL_ActionScope scope = SCOPE_GLOBAL,
int aDefaultHotKey = 0,
const wxString& menuItem = wxT(""),
const wxString& menuDesc = wxT("")
) :
m_name(name),
m_scope(scope),
m_defaultHotKey(aDefaultHotKey),
m_currentHotKey(aDefaultHotKey),
m_menuItem(menuItem),
m_menuDescription(menuDesc) {}
bool operator == ( const TOOL_ACTION& rhs ) const
{
return m_id == rhs.m_id;
}
bool operator != ( const TOOL_ACTION& rhs ) const
{
return m_id != rhs.m_id;
}
bool hasHotKey() const
{
return m_currentHotKey > 0;
}
private:
friend class TOOL_MANAGER;
void setId ( int aId )
{
m_id = aId;
}
// name of the action (convention is: app.[tool.]action.name)
std::string m_name;
TOOL_ActionScope m_scope;
int m_defaultHotKey;
int m_currentHotKey;
// Menu item text
wxString m_menuItem;
// Pop-up help
wxString m_menuDescription;
//KiBitmap m_bitmap;
// Unique ID for fast matching. Assigned by TOOL_MANAGER
int m_id;
// Origin of the action
TOOL_BASE *m_origin;
// Originating UI object
wxWindow *m_uiOrigin;
};
#endif
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.
/*
* 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_OPTIMIZER_H
#define __PNS_OPTIMIZER_H
#include <boost/unordered_map.hpp>
#include <boost/shared_ptr.hpp>
#include <geometry/shape_index_list.h>
#include <geometry/shape_line_chain.h>
class PNS_NODE;
class PNS_LINE;
class PNS_ROUTER;
/**
* Class PNS_COST_ESTIMATOR
*
* 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() {};
static int CornerCost ( const SEG& a, const SEG& b);
static int CornerCost ( const SHAPE_LINE_CHAIN& aLine );
static int CornerCost ( const PNS_LINE& aLine);
void Add(PNS_LINE &aLine);
void Remove (PNS_LINE &aLine);
void Replace(PNS_LINE &aOldLine, PNS_LINE& aNewLine);
bool IsBetter( PNS_COST_ESTIMATOR& aOther, double aLengthTollerance, double aCornerTollerace ) const;
double GetLengthCost() const { return m_lengthCost; }
double GetCornerCost() const { return m_cornerCost; }
private:
double m_lengthCost;
int m_cornerCost;
};
/**
* Class PNS_OPTIMIZER
*
* Performs various optimizations of the lines being routed, attempting to make the lines shorter
* and less cornery. There are 3 kinds of optimizations so far:
* - Merging obtuse segments (MERGE_OBTUSE): tries to join together as many
* obtuse segments as possible without causing collisions
* - Rerouting path between pair of line corners with a 2-segment "\__" line and iteratively repeating
* the procedure as long as the total cost of the line keeps decreasing
* - "Smart Pads" - that is, rerouting pad/via exits to make them look nice (SMART_PADS).
**/
class PNS_OPTIMIZER
{
public:
enum OptimizationEffort {
MERGE_SEGMENTS = 0x1,
SMART_PADS = 0x2,
MERGE_OBTUSE = 0x4
};
PNS_OPTIMIZER( PNS_NODE *aWorld );
~PNS_OPTIMIZER();
///> a quick shortcut to optmize a line without creating and setting up an optimizer
static bool Optimize ( PNS_LINE *aLine, int aEffortLevel, PNS_NODE *aWorld = NULL );
bool Optimize ( PNS_LINE *aLine, PNS_LINE *aResult = NULL, int aStartVertex = 0, int aEndVertex = -1);
void SetWorld(PNS_NODE *aNode) { m_world = aNode; }
void CacheStaticItem (PNS_ITEM *aItem);
void CacheRemove( PNS_ITEM *aItem );
void ClearCache( bool aStaticOnly = false );
void SetCollisionMask ( int aMask )
{
m_collisionKindMask = aMask;
}
void SetEffortLevel ( int aEffort )
{
m_effortLevel = aEffort;
}
private:
static const int MaxCachedItems = 256;
typedef std::vector<SHAPE_LINE_CHAIN> BreakoutList;
struct CacheVisitor;
struct CachedItem
{
int hits;
bool isStatic;
};
bool mergeObtuse (PNS_LINE *aLine);
bool mergeFull (PNS_LINE *aLine);
bool removeUglyCorners (PNS_LINE *aLine);
bool runSmartPads(PNS_LINE *aLine);
bool mergeStep ( PNS_LINE *aLine, SHAPE_LINE_CHAIN& aCurrentLine, int step );
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;
int smartPadsSingle( PNS_LINE *aLine, PNS_ITEM *aPad, bool aEnd, int aEndVertex );
PNS_ITEM *findPadOrVia ( int aLayer, int aNet, const VECTOR2I& aP) const;
SHAPE_INDEX_LIST<PNS_ITEM *> m_cache;
typedef boost::unordered_map<PNS_ITEM*, CachedItem> CachedItemTags;
CachedItemTags m_cacheTags;
PNS_NODE *m_world;
int m_collisionKindMask;
int m_effortLevel;
bool m_keepPostures;
};
#endif
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_H
#define __PNS_ROUTER_H
#include <list>
#include <boost/optional.hpp>
#include <boost/unordered_set.hpp>
#include <geometry/shape_line_chain.h>
#include "pns_routing_settings.h"
#include "pns_item.h"
#include "pns_itemset.h"
class BOARD;
class BOARD_ITEM;
class D_PAD;
class TRACK;
class SEGVIA;
class PNS_NODE;
class PNS_LINE_PLACER;
class PNS_ITEM;
class PNS_LINE;
class PNS_SOLID;
class PNS_SEGMENT;
class PNS_JOINT;
class PNS_VIA;
class PNS_CLEARANCE_FUNC;
class VIEW_GROUP;
namespace KiGfx {
class VIEW;
class VIEW_GROUP;
};
/**
* Class PNS_ROUTER
*
* Main router class.
*/
class PNS_ROUTER {
private:
enum RouterState {
IDLE,
START_ROUTING,
ROUTE_TRACK,
FINISH_TRACK
};
public:
PNS_ROUTER ();
~PNS_ROUTER ();
static PNS_ROUTER *GetInstance();
void ClearWorld();
void SetBoard( BOARD *aBoard );
void SyncWorld();
void SetView(KiGfx::VIEW *aView);
bool RoutingInProgress() const;
void StartRouting(const VECTOR2I& aP, PNS_ITEM *aItem);
void Move(const VECTOR2I& aP, PNS_ITEM *aItem);
bool FixRoute(const VECTOR2I& aP, PNS_ITEM *aItem);
void StopRouting();
const VECTOR2I GetCurrentEnd() const;
int GetClearance(const PNS_ITEM* a, const PNS_ITEM *b ) const;
PNS_NODE* GetWorld() const
{
return m_world;
}
void FlipPosture();
void DisplayItem ( const PNS_ITEM *aItem, bool aIsHead = false );
void DisplayDebugLine ( const SHAPE_LINE_CHAIN &aLine, int aType = 0, int aWidth = 0);
void DisplayDebugBox ( const BOX2I& aBox, int aType = 0, int aWidth = 0);
void EraseView ( );
void SwitchLayer (int layer );
int GetCurrentLayer() const { return m_currentLayer; }
void ToggleViaPlacement ();
void SetCurrentWidth(int w);
void SetCurrentViaDiameter(int d) { m_currentViaDiameter = d;}
void SetCurrentViaDrill(int d) { m_currentViaDrill = d;}
int GetCurrentWidth() const { return m_currentWidth; }
int GetCurrentViaDiameter() const { return m_currentViaDiameter; }
int GetCurrentViaDrill() const { return m_currentViaDrill; }
int GetCurrentNet() const { return m_currentNet; }
PNS_CLEARANCE_FUNC *GetClearanceFunc() const
{
return m_clearanceFunc;
}
bool IsPlacingVia() const
{
return m_placingVia;
}
int NextCopperLayer( bool aUp );
//typedef boost::optional<hoverItem> optHoverItem;
const PNS_ITEMSET QueryHoverItems(const VECTOR2I& aP);
const VECTOR2I SnapToItem( PNS_ITEM *item, VECTOR2I aP, bool& aSplitsSegment );
private:
void clearViewFlags();
//optHoverItem queryHoverItemEx(const VECTOR2I& aP);
PNS_ITEM *pickSingleItem ( PNS_ITEMSET &aItems ) const; //std::vector<PNS_ITEM*> aItems) const;
void splitAdjacentSegments(PNS_NODE *aNode, PNS_ITEM *aSeg, const VECTOR2I& aP ); //optHoverItem& aItem);
void commitRouting ( PNS_NODE *aNode );
PNS_NODE *removeLoops ( PNS_NODE *aNode, PNS_SEGMENT *aLatestSeg );
PNS_NODE *removeLoops ( PNS_NODE *aNode, PNS_LINE *aNewLine );
PNS_VIA *checkLoneVia ( PNS_JOINT* aJoint ) const;
PNS_ITEM *syncPad( D_PAD *aPad );
PNS_ITEM *syncTrack( TRACK *aTrack );
PNS_ITEM *syncVia( SEGVIA *aVia );
void commitPad( PNS_SOLID *aPad );
void commitSegment( PNS_SEGMENT *aTrack );
void commitVia( PNS_VIA *aVia );
void highlightCurrent( bool enabled );
int m_currentLayer;
int m_currentNet;
int m_currentWidth;
int m_currentViaDiameter;
int m_currentViaDrill;
bool m_start_diagonal;
RouterState m_state;
BOARD *m_board;
PNS_NODE *m_world;
PNS_LINE_PLACER *m_placer;
KiGfx::VIEW *m_view;
KiGfx::VIEW_GROUP *m_previewItems;
VECTOR2I m_currentEnd;
VECTOR2I m_currentStart;
VECTOR2I m_originalStart;
bool m_placingVia;
bool m_startsOnVia;
// optHoverItem m_startItem, m_endItem;
PNS_ROUTING_SETTINGS m_settings;
PNS_CLEARANCE_FUNC *m_clearanceFunc;
boost::unordered_set<BOARD_ITEM *> m_hiddenItems;
};
#endif
\ 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_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.
/*
* 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 <math/vector2d.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_circle.h>
#include "pns_solid.h"
#include "pns_utils.h"
const SHAPE_LINE_CHAIN PNS_SOLID::Hull(int aClearance, int aWalkaroundThickness) const
{
switch(m_shape->Type())
{
case SH_RECT:
{
SHAPE_RECT *rect = static_cast<SHAPE_RECT*> (m_shape);
return OctagonalHull( rect->GetPosition(),
rect->GetSize(),
aClearance + 1,
0.2 * aClearance );
}
case SH_CIRCLE:
{
SHAPE_CIRCLE *circle = static_cast<SHAPE_CIRCLE*> (m_shape);
int r = circle->GetRadius();
return OctagonalHull( circle->GetCenter() - VECTOR2I(r, r),
VECTOR2I(2 * r, 2 * r),
aClearance + 1,
0.52 * (r + aClearance) );
}
default:
break;
}
return SHAPE_LINE_CHAIN();
}
PNS_ITEM *PNS_SOLID::Clone() const
{
// solids are never cloned as the shove algorithm never moves them
assert(false);
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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