/* * 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; }; /** * 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