/* * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013 CERN * Author: Tomasz Wlostowski * * 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 . */ #ifndef __PNS_NODE_H #define __PNS_NODE_H #include #include #include #include #include #include #include #include #include #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 OptObstacle; typedef std::vector ItemVector; typedef std::vector Obstacles; typedef boost::optional 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& 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& aConnectedJoints ); ///> Destroys all child nodes. Applicable only to the root node. void KillChildren(); void AllItemsInNet( int aNet, std::list& aItems ); private: struct obstacleVisitor; typedef boost::unordered_multimap 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 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 m_children; ///> hash of root's items that are more recent in this node boost::unordered_set 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