2013-09-18 17:55:16 +00:00
|
|
|
/*
|
|
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
|
|
*
|
2014-05-14 13:53:54 +00:00
|
|
|
* Copyright (C) 2013-2014 CERN
|
2023-04-09 19:25:22 +00:00
|
|
|
* Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
|
2021-01-27 22:15:38 +00:00
|
|
|
*
|
|
|
|
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* 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.
|
2013-09-26 21:53:54 +00:00
|
|
|
*
|
2013-09-18 17:55:16 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
2014-05-14 13:53:54 +00:00
|
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
2013-09-18 17:55:16 +00:00
|
|
|
*/
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
#ifndef __PNS_NODE_H
|
|
|
|
#define __PNS_NODE_H
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
#include <list>
|
2022-08-30 12:52:34 +00:00
|
|
|
#include <set>
|
2020-10-08 21:57:08 +00:00
|
|
|
#include <core/minoptmax.h>
|
2013-09-18 17:55:16 +00:00
|
|
|
|
|
|
|
#include <geometry/shape_line_chain.h>
|
|
|
|
#include <geometry/shape_index.h>
|
|
|
|
|
|
|
|
#include "pns_item.h"
|
|
|
|
#include "pns_joint.h"
|
|
|
|
#include "pns_itemset.h"
|
|
|
|
|
2016-08-29 14:38:11 +00:00
|
|
|
namespace PNS {
|
|
|
|
|
2019-05-17 00:13:21 +00:00
|
|
|
class ARC;
|
2016-08-29 17:31:13 +00:00
|
|
|
class SEGMENT;
|
|
|
|
class LINE;
|
|
|
|
class SOLID;
|
|
|
|
class VIA;
|
|
|
|
class INDEX;
|
|
|
|
class ROUTER;
|
|
|
|
class NODE;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2015-02-18 00:29:54 +00:00
|
|
|
|
2020-10-08 21:57:08 +00:00
|
|
|
enum class CONSTRAINT_TYPE
|
|
|
|
{
|
|
|
|
CT_CLEARANCE = 1,
|
|
|
|
CT_DIFF_PAIR_GAP = 2,
|
|
|
|
CT_LENGTH = 3,
|
2020-10-08 22:01:09 +00:00
|
|
|
CT_WIDTH = 4,
|
|
|
|
CT_VIA_DIAMETER = 5,
|
2020-12-30 20:27:20 +00:00
|
|
|
CT_VIA_HOLE = 6,
|
|
|
|
CT_HOLE_CLEARANCE = 7,
|
2021-01-01 00:29:05 +00:00
|
|
|
CT_EDGE_CLEARANCE = 8,
|
|
|
|
CT_HOLE_TO_HOLE = 9
|
2020-10-08 21:57:08 +00:00
|
|
|
};
|
|
|
|
|
2022-08-30 12:52:34 +00:00
|
|
|
/**
|
|
|
|
* An abstract function object, returning a design rule (clearance, diff pair gap, etc) required
|
|
|
|
* between two items.
|
|
|
|
*/
|
|
|
|
|
2020-10-08 21:57:08 +00:00
|
|
|
struct CONSTRAINT
|
|
|
|
{
|
|
|
|
CONSTRAINT_TYPE m_Type;
|
2021-01-01 01:02:06 +00:00
|
|
|
MINOPTMAX<int> m_Value;
|
|
|
|
bool m_Allowed;
|
|
|
|
wxString m_RuleName;
|
|
|
|
wxString m_FromName;
|
|
|
|
wxString m_ToName;
|
2020-10-08 21:57:08 +00:00
|
|
|
};
|
|
|
|
|
2022-08-30 12:52:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Hold an object colliding with another object, along with some useful data about the collision.
|
|
|
|
*/
|
|
|
|
struct OBSTACLE
|
|
|
|
{
|
|
|
|
ITEM* m_head = nullptr; ///< Line we search collisions against
|
|
|
|
ITEM* m_item = nullptr; ///< Item found to be colliding with m_head
|
|
|
|
VECTOR2I m_ipFirst; ///< First intersection between m_head and m_hull
|
|
|
|
int m_clearance;
|
|
|
|
VECTOR2I m_pos;
|
|
|
|
int m_distFirst; ///< ... and the distance thereof
|
|
|
|
int m_maxFanoutWidth; ///< worst case (largest) width of the tracks connected to the item
|
|
|
|
|
|
|
|
CONSTRAINT_TYPE m_violatingConstraint;
|
|
|
|
|
|
|
|
bool operator==(const OBSTACLE& other) const
|
|
|
|
{
|
|
|
|
return m_head == other.m_head && m_item == other.m_item;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator<(const OBSTACLE& other) const
|
|
|
|
{
|
|
|
|
if( (uintptr_t)m_head < (uintptr_t)other.m_head )
|
|
|
|
return true;
|
|
|
|
else if ( m_head == other.m_head )
|
|
|
|
return (uintptr_t)m_item < (uintptr_t)other.m_item;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct COLLISION_SEARCH_OPTIONS
|
|
|
|
{
|
|
|
|
bool m_differentNetsOnly = true;
|
|
|
|
int m_overrideClearance = -1;
|
|
|
|
int m_limitCount = -1;
|
|
|
|
int m_kindMask = -1;
|
|
|
|
bool m_useClearanceEpsilon = true;
|
|
|
|
std::set<ITEM*>* m_restrictedSet = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct COLLISION_SEARCH_CONTEXT
|
|
|
|
{
|
|
|
|
COLLISION_SEARCH_CONTEXT( std::set<OBSTACLE>& aObs, const COLLISION_SEARCH_OPTIONS aOpts ) :
|
|
|
|
obstacles( aObs ),
|
|
|
|
options( aOpts )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
std::set<OBSTACLE>& obstacles;
|
|
|
|
const COLLISION_SEARCH_OPTIONS options;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
class RULE_RESOLVER
|
2015-02-18 00:29:54 +00:00
|
|
|
{
|
|
|
|
public:
|
2016-08-29 17:31:13 +00:00
|
|
|
virtual ~RULE_RESOLVER() {}
|
2015-02-18 00:29:54 +00:00
|
|
|
|
2022-06-03 21:20:47 +00:00
|
|
|
virtual int Clearance( const ITEM* aA, const ITEM* aB, bool aUseClearanceEpsilon = true ) = 0;
|
2021-01-01 00:29:05 +00:00
|
|
|
|
2016-08-15 15:16:47 +00:00
|
|
|
virtual int DpCoupledNet( int aNet ) = 0;
|
|
|
|
virtual int DpNetPolarity( int aNet ) = 0;
|
2020-10-08 22:01:09 +00:00
|
|
|
virtual bool DpNetPair( const ITEM* aItem, int& aNetP, int& aNetN ) = 0;
|
|
|
|
|
2022-08-19 17:34:53 +00:00
|
|
|
virtual bool IsInNetTie( const ITEM* aA ) = 0;
|
|
|
|
virtual bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos,
|
|
|
|
const PNS::ITEM* aCollidingItem )= 0;
|
|
|
|
|
2022-09-14 21:02:30 +00:00
|
|
|
virtual bool IsKeepout( const ITEM* aA, const ITEM* aB ) = 0;
|
2022-08-19 17:34:53 +00:00
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
virtual bool QueryConstraint( CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA,
|
|
|
|
const PNS::ITEM* aItemB, int aLayer,
|
|
|
|
PNS::CONSTRAINT* aConstraint ) = 0;
|
2021-01-27 22:15:38 +00:00
|
|
|
|
2018-05-19 00:50:52 +00:00
|
|
|
virtual wxString NetName( int aNet ) = 0;
|
2021-11-25 20:38:04 +00:00
|
|
|
|
|
|
|
virtual void ClearCacheForItem( const ITEM* aItem ) {}
|
2022-11-16 21:05:12 +00:00
|
|
|
virtual void ClearCaches() {}
|
2022-08-15 13:31:43 +00:00
|
|
|
|
2022-08-29 20:21:46 +00:00
|
|
|
virtual int ClearanceEpsilon() const { return 0; }
|
2013-09-18 17:55:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
class OBSTACLE_VISITOR
|
|
|
|
{
|
2016-08-15 15:16:49 +00:00
|
|
|
public:
|
2016-08-29 17:31:13 +00:00
|
|
|
OBSTACLE_VISITOR( const ITEM* aItem );
|
2016-08-15 15:16:49 +00:00
|
|
|
|
2020-02-05 22:19:14 +00:00
|
|
|
virtual ~OBSTACLE_VISITOR()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-07-19 23:56:05 +00:00
|
|
|
void SetWorld( const NODE* aNode, const NODE* aOverride = nullptr );
|
2016-08-15 15:16:49 +00:00
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
virtual bool operator()( ITEM* aCandidate ) = 0;
|
2016-08-15 15:16:49 +00:00
|
|
|
|
|
|
|
protected:
|
2016-08-29 17:31:13 +00:00
|
|
|
bool visit( ITEM* aCandidate );
|
2016-08-15 15:16:49 +00:00
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
protected:
|
2021-01-27 22:15:38 +00:00
|
|
|
const ITEM* m_item; ///< the item we are looking for collisions with
|
2016-08-15 15:16:49 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
const NODE* m_node; ///< node we are searching in (either root or a branch)
|
|
|
|
const NODE* m_override; ///< node that overrides root entries
|
2015-02-18 00:29:54 +00:00
|
|
|
};
|
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Keep the router "world" - i.e. all the tracks, vias, solids in a hierarchical and indexed way.
|
2013-09-18 17:55:16 +00:00
|
|
|
*
|
|
|
|
* Features:
|
2021-01-27 22:15:38 +00:00
|
|
|
* - spatial-indexed container for PCB item shapes.
|
|
|
|
* - collision search & clearance checking.
|
|
|
|
* - assembly of lines connecting joints, finding loops and unique paths.
|
|
|
|
* - lightweight cloning/branching (for recursive optimization and shove springback).
|
2013-09-18 17:55:16 +00:00
|
|
|
**/
|
2022-08-29 20:21:46 +00:00
|
|
|
class NODE : public ITEM_OWNER
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
2013-09-18 17:55:16 +00:00
|
|
|
public:
|
2022-03-03 23:58:14 +00:00
|
|
|
|
|
|
|
///< Supported item types
|
|
|
|
enum COLLISION_QUERY_SCOPE
|
|
|
|
{
|
|
|
|
CQS_ALL_RULES = 1, ///< check all rules
|
|
|
|
CQS_IGNORE_HOLE_CLEARANCE = 2 ///< check everything except hole2hole / hole2copper
|
|
|
|
};
|
|
|
|
|
2022-08-25 22:50:47 +00:00
|
|
|
typedef std::optional<OBSTACLE> OPT_OBSTACLE;
|
2021-01-01 01:02:06 +00:00
|
|
|
typedef std::vector<ITEM*> ITEM_VECTOR;
|
2022-08-30 12:52:34 +00:00
|
|
|
typedef std::set<OBSTACLE> OBSTACLES;
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
NODE();
|
|
|
|
~NODE();
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Return the expected clearance between items a and b.
|
2022-06-03 21:20:47 +00:00
|
|
|
int GetClearance( const ITEM* aA, const ITEM* aB, bool aUseClearanceEpsilon = true ) const;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Return the pre-set worst case clearance between any pair of items.
|
2014-05-16 11:37:31 +00:00
|
|
|
int GetMaxClearance() const
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
|
|
|
return m_maxClearance;
|
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Set the worst-case clearance between any pair of items.
|
2014-05-16 11:37:31 +00:00
|
|
|
void SetMaxClearance( int aClearance )
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
|
|
|
m_maxClearance = aClearance;
|
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Assign a clearance resolution function object.
|
2016-08-29 17:31:13 +00:00
|
|
|
void SetRuleResolver( RULE_RESOLVER* aFunc )
|
2016-08-15 15:16:47 +00:00
|
|
|
{
|
|
|
|
m_ruleResolver = aFunc;
|
|
|
|
}
|
|
|
|
|
2019-07-24 15:19:03 +00:00
|
|
|
RULE_RESOLVER* GetRuleResolver() const
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
2016-08-15 15:16:47 +00:00
|
|
|
return m_ruleResolver;
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Return the number of joints.
|
2013-09-26 21:53:54 +00:00
|
|
|
int JointCount() const
|
|
|
|
{
|
|
|
|
return m_joints.size();
|
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Return the number of nodes in the inheritance chain (wrs to the root node).
|
2014-11-02 16:25:04 +00:00
|
|
|
int Depth() const
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
|
|
|
return m_depth;
|
|
|
|
}
|
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Find items colliding (closer than clearance) with the item \a aItem.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
|
|
|
* @param aItem item to check collisions against
|
|
|
|
* @param aObstacles set of colliding objects found
|
|
|
|
* @param aKindMask mask of obstacle types to take into account
|
|
|
|
* @param aLimitCount stop looking for collisions after finding this number of colliding items
|
|
|
|
* @return number of obstacles found
|
|
|
|
*/
|
2022-08-15 13:31:43 +00:00
|
|
|
int QueryColliding( const ITEM* aItem, OBSTACLES& aObstacles,
|
2022-08-30 12:52:34 +00:00
|
|
|
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS() ) const;
|
2016-08-29 17:31:13 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
int QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints,
|
|
|
|
LAYER_RANGE aLayerMask = LAYER_RANGE::All(), int aKindMask = ITEM::ANY_T );
|
2020-02-19 17:41:13 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Follow the line in search of an obstacle that is nearest to the starting to the line's
|
2021-01-01 01:02:06 +00:00
|
|
|
* starting point.
|
2021-01-27 22:15:38 +00:00
|
|
|
*
|
2020-12-30 20:27:20 +00:00
|
|
|
* @param aLine the item to find collisions with
|
2014-05-14 13:53:54 +00:00
|
|
|
* @param aKindMask mask of obstacle types to take into account
|
2022-06-03 21:20:47 +00:00
|
|
|
* @param aRestrictedSet is an optional set of items that should be considered as obstacles
|
2014-05-14 13:53:54 +00:00
|
|
|
* @return the obstacle, if found, otherwise empty.
|
|
|
|
*/
|
2022-08-30 12:52:34 +00:00
|
|
|
OPT_OBSTACLE NearestObstacle( const LINE* aLine,
|
2022-08-15 13:31:43 +00:00
|
|
|
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS() );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Check if the item collides with anything else in the world, and if found, returns the
|
2021-01-01 01:02:06 +00:00
|
|
|
* obstacle.
|
2021-01-27 22:15:38 +00:00
|
|
|
*
|
2014-05-14 13:53:54 +00:00
|
|
|
* @param aItem the item to find collisions with
|
|
|
|
* @param aKindMask mask of obstacle types to take into account
|
|
|
|
* @return the obstacle, if found, otherwise empty.
|
|
|
|
*/
|
2021-01-27 22:15:38 +00:00
|
|
|
OPT_OBSTACLE CheckColliding( const ITEM* aItem, int aKindMask = ITEM::ANY_T );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
|
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Check if any item in the set collides with anything else in the world, and if found,
|
2021-01-01 01:02:06 +00:00
|
|
|
* returns the obstacle.
|
2021-01-27 22:15:38 +00:00
|
|
|
*
|
|
|
|
* @param aSet set of items to find collisions with.
|
|
|
|
* @param aKindMask mask of obstacle types to take into account.
|
2014-05-14 13:53:54 +00:00
|
|
|
* @return the obstacle, if found, otherwise empty.
|
|
|
|
*/
|
2021-01-27 22:15:38 +00:00
|
|
|
OPT_OBSTACLE CheckColliding( const ITEM_SET& aSet, int aKindMask = ITEM::ANY_T );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Find all items that contain the point \a aPoint.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aPoint the point.
|
|
|
|
* @return the items.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
const ITEM_SET HitTest( const VECTOR2I& aPoint ) const;
|
2014-05-14 13:53:54 +00:00
|
|
|
|
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Add an item to the current node.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aSegment item to add.
|
2014-11-02 16:25:04 +00:00
|
|
|
* @param aAllowRedundant if true, duplicate items are allowed (e.g. a segment or via
|
2021-01-27 22:15:38 +00:00
|
|
|
* at the same coordinates as an existing one).
|
2018-02-08 10:32:13 +00:00
|
|
|
* @return true if added
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2022-09-11 21:17:45 +00:00
|
|
|
bool Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant = false );
|
|
|
|
void Add( std::unique_ptr< SOLID >&& aSolid );
|
|
|
|
void Add( std::unique_ptr< VIA >&& aVia );
|
|
|
|
bool Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant = false );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2016-08-30 15:28:35 +00:00
|
|
|
void Add( LINE& aLine, bool aAllowRedundant = false );
|
|
|
|
|
2022-06-27 21:07:25 +00:00
|
|
|
void AddEdgeExclusion( std::unique_ptr<SHAPE> aShape );
|
|
|
|
bool QueryEdgeExclusions( const VECTOR2I& aPos ) const;
|
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Remove an item from this branch.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2019-05-17 00:13:21 +00:00
|
|
|
void Remove( ARC* aArc );
|
2016-08-30 17:01:30 +00:00
|
|
|
void Remove( SOLID* aSolid );
|
|
|
|
void Remove( VIA* aVia );
|
|
|
|
void Remove( SEGMENT* aSegment );
|
2016-08-29 17:31:13 +00:00
|
|
|
void Remove( ITEM* aItem );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2015-02-18 00:29:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Removes a line from this branch.
|
2015-02-18 00:29:54 +00:00
|
|
|
*
|
2017-06-22 07:01:29 +00:00
|
|
|
* @param aLine item to remove
|
2015-02-18 00:29:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
void Remove( LINE& aLine );
|
2015-02-18 00:29:54 +00:00
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Replace an item with another one.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
|
|
|
* @param aOldItem item to be removed
|
|
|
|
* @param aNewItem item add instead
|
|
|
|
*/
|
2022-09-11 21:17:45 +00:00
|
|
|
void Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem );
|
2016-08-30 15:28:35 +00:00
|
|
|
void Replace( LINE& aOldLine, LINE& aNewLine );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Create a lightweight copy (called branch) of self that tracks the changes (added/removed
|
|
|
|
* items) wrs to the root.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @note If there are any branches in use, their parents must **not** be deleted.
|
|
|
|
*
|
|
|
|
* @return the new branch.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
NODE* Branch();
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2014-11-02 16:25:04 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Follow the joint map to assemble a line connecting two non-trivial joints starting from
|
|
|
|
* segment \a aSeg.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aSeg the initial segment.
|
|
|
|
* @param aOriginSegmentIndex index of aSeg in the resulting line.
|
2021-12-05 18:35:28 +00:00
|
|
|
* @param aStopAtLockedJoints will terminate the line at the first locked joint encountered
|
|
|
|
* @param aFollowLockedSegments will consider a joint between a locked segment and an unlocked
|
|
|
|
* segment of the same width as a trivial joint.
|
2014-05-14 13:53:54 +00:00
|
|
|
* @return the line
|
|
|
|
*/
|
2021-07-19 23:56:05 +00:00
|
|
|
const LINE AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex = nullptr,
|
2021-12-05 18:35:28 +00:00
|
|
|
bool aStopAtLockedJoints = false,
|
|
|
|
bool aFollowLockedSegments = false );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Print the contents and joints structure.
|
2014-05-16 11:37:31 +00:00
|
|
|
void Dump( bool aLong = false );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Return the list of items removed and added in this branch with respect to the root branch.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aRemoved removed items.
|
|
|
|
* @param aAdded added items.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2014-05-16 11:37:31 +00:00
|
|
|
void GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Apply the changes from a given branch (aNode) to the root branch.
|
|
|
|
*
|
|
|
|
* Calling on a non-root branch will fail. Calling commit also kills all children nodes of
|
|
|
|
* the root branch.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aNode node to commit changes from.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
void Commit( NODE* aNode );
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Search for a joint at a given position, layer and belonging to given net.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @return the joint, if found, otherwise empty.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2022-08-29 20:21:46 +00:00
|
|
|
const JOINT* FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ) const;
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
void LockJoint( const VECTOR2I& aPos, const ITEM* aItem, bool aLock );
|
2015-08-03 19:11:51 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Search for a joint at a given position, linked to given item.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @return the joint, if found, otherwise empty.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2022-08-29 20:21:46 +00:00
|
|
|
const JOINT* FindJoint( const VECTOR2I& aPos, const ITEM* aItem ) const
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
|
|
|
return FindJoint( aPos, aItem->Layers().Start(), aItem->Net() );
|
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Find all lines between a pair of joints. Used by the loop removal procedure.
|
|
|
|
int FindLinesBetweenJoints( const JOINT& aA, const JOINT& aB, std::vector<LINE>& aLines );
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Find the joints corresponding to the ends of line \a aLine.
|
2016-08-29 17:31:13 +00:00
|
|
|
void FindLineEnds( const LINE& aLine, JOINT& aA, JOINT& aB );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Destroy all child nodes. Applicable only to the root node.
|
2013-09-26 21:53:54 +00:00
|
|
|
void KillChildren();
|
|
|
|
|
2020-09-04 23:10:26 +00:00
|
|
|
void AllItemsInNet( int aNet, std::set<ITEM*>& aItems, int aKindMask = -1 );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2022-08-15 13:31:43 +00:00
|
|
|
void ClearRanks( int aMarkerMask = MK_HEAD | MK_VIOLATION );
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2019-07-24 15:19:03 +00:00
|
|
|
void RemoveByMarker( int aMarker );
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2020-10-17 12:52:18 +00:00
|
|
|
ITEM* FindItemByParent( const BOARD_ITEM* aParent );
|
2015-07-02 14:09:56 +00:00
|
|
|
|
2015-09-14 16:40:29 +00:00
|
|
|
bool HasChildren() const
|
|
|
|
{
|
|
|
|
return !m_children.empty();
|
|
|
|
}
|
|
|
|
|
2020-02-07 19:57:24 +00:00
|
|
|
NODE* GetParent() const
|
|
|
|
{
|
|
|
|
return m_parent;
|
|
|
|
}
|
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Check if this branch contains an updated version of the m_item from the root branch.
|
2016-08-29 17:31:13 +00:00
|
|
|
bool Overrides( ITEM* aItem ) const
|
2016-08-15 15:16:49 +00:00
|
|
|
{
|
|
|
|
return m_override.find( aItem ) != m_override.end();
|
|
|
|
}
|
|
|
|
|
2021-06-03 20:36:06 +00:00
|
|
|
void FixupVirtualVias();
|
|
|
|
|
2022-09-11 21:17:45 +00:00
|
|
|
void AddRaw( ITEM* aItem, bool aAllowRedundant = false )
|
|
|
|
{
|
|
|
|
add( aItem, aAllowRedundant );
|
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2022-10-23 22:34:42 +00:00
|
|
|
private:
|
2022-09-11 21:17:45 +00:00
|
|
|
void add( ITEM* aItem, bool aAllowRedundant = false );
|
2022-10-23 22:34:42 +00:00
|
|
|
|
2013-09-26 21:53:54 +00:00
|
|
|
/// nodes are not copyable
|
2016-08-29 17:31:13 +00:00
|
|
|
NODE( const NODE& aB );
|
|
|
|
NODE& operator=( const NODE& aB );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Try to find matching joint and creates a new one if not found.
|
|
|
|
JOINT& touchJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, int aNet );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Touch a joint and links it to an m_item.
|
2017-01-25 09:33:49 +00:00
|
|
|
void linkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, int aNet, ITEM* aWhere );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Unlink an item from a joint.
|
2017-01-25 09:33:49 +00:00
|
|
|
void unlinkJoint( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, int aNet, ITEM* aWhere );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Helpers for adding/removing items.
|
2016-08-29 17:31:13 +00:00
|
|
|
void addSolid( SOLID* aSeg );
|
2016-08-30 15:28:35 +00:00
|
|
|
void addSegment( SEGMENT* aSeg );
|
2016-08-29 17:31:13 +00:00
|
|
|
void addVia( VIA* aVia );
|
2019-05-17 00:13:21 +00:00
|
|
|
void addArc( ARC* aVia );
|
2022-08-30 12:52:34 +00:00
|
|
|
void addHole( HOLE* aHole );
|
2017-01-25 09:33:49 +00:00
|
|
|
|
2016-08-30 17:01:30 +00:00
|
|
|
void removeSolidIndex( SOLID* aSeg );
|
|
|
|
void removeSegmentIndex( SEGMENT* aSeg );
|
|
|
|
void removeViaIndex( VIA* aVia );
|
2019-05-17 00:13:21 +00:00
|
|
|
void removeArcIndex( ARC* aVia );
|
2016-08-29 17:31:13 +00:00
|
|
|
|
|
|
|
void doRemove( ITEM* aItem );
|
2013-09-26 21:53:54 +00:00
|
|
|
void unlinkParent();
|
|
|
|
void releaseChildren();
|
2015-08-03 19:11:51 +00:00
|
|
|
void releaseGarbage();
|
2022-08-29 20:21:46 +00:00
|
|
|
void rebuildJoint( const JOINT* aJoint, const ITEM* aItem );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
|
|
|
bool isRoot() const
|
|
|
|
{
|
2021-07-19 23:56:05 +00:00
|
|
|
return m_parent == nullptr;
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
SEGMENT* findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr,
|
|
|
|
int aNet );
|
2016-08-29 17:31:13 +00:00
|
|
|
SEGMENT* findRedundantSegment( SEGMENT* aSeg );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
ARC* findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const LAYER_RANGE& lr, int aNet );
|
2019-05-17 00:13:21 +00:00
|
|
|
ARC* findRedundantArc( ARC* aSeg );
|
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Scan the joint map, forming a line starting from segment (current).
|
2021-02-20 16:57:28 +00:00
|
|
|
void followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, int aLimit,
|
2021-01-05 22:55:55 +00:00
|
|
|
VECTOR2I* aCorners, LINKED_ITEM** aSegments, bool* aArcReversed,
|
2021-12-05 18:35:28 +00:00
|
|
|
bool& aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments );
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-01 01:02:06 +00:00
|
|
|
private:
|
2021-01-27 22:15:38 +00:00
|
|
|
struct DEFAULT_OBSTACLE_VISITOR;
|
|
|
|
typedef std::unordered_multimap<JOINT::HASH_TAG, JOINT, JOINT::JOINT_TAG_HASH> JOINT_MAP;
|
|
|
|
typedef JOINT_MAP::value_type TagJointPair;
|
|
|
|
|
|
|
|
JOINT_MAP m_joints; ///< hash table with the joints, linking the items. Joints
|
|
|
|
///< are hashed by their position, layer set and net.
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
NODE* m_parent; ///< node this node was branched from
|
|
|
|
NODE* m_root; ///< root node of the whole hierarchy
|
|
|
|
std::set<NODE*> m_children; ///< list of nodes branched from this one
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
std::unordered_set<ITEM*> m_override; ///< hash of root's items that have been changed
|
|
|
|
///< in this node
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
int m_maxClearance; ///< worst case item-item clearance
|
|
|
|
RULE_RESOLVER* m_ruleResolver; ///< Design rules resolver
|
|
|
|
INDEX* m_index; ///< Geometric/Net index of the items
|
|
|
|
int m_depth; ///< depth of the node (number of parent nodes in the
|
|
|
|
///< inheritance chain)
|
2015-02-18 00:29:54 +00:00
|
|
|
|
2022-06-27 21:07:25 +00:00
|
|
|
std::vector< std::unique_ptr<SHAPE> > m_edgeExclusions;
|
|
|
|
|
2017-11-01 11:14:16 +00:00
|
|
|
std::unordered_set<ITEM*> m_garbageItems;
|
2013-09-18 17:55:16 +00:00
|
|
|
};
|
|
|
|
|
2016-08-29 14:38:11 +00:00
|
|
|
}
|
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
#endif
|