283 lines
8.5 KiB
C++
283 lines
8.5 KiB
C++
/*
|
|
* 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;
|
|
virtual ~PNS_CLEARANCE_FUNC() {}
|
|
};
|
|
|
|
/**
|
|
* 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 ) const;
|
|
|
|
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
|