2013-09-18 17:55:16 +00:00
|
|
|
/*
|
|
|
|
* KiRouter - a push-and-(sometimes-)shove PCB router
|
|
|
|
*
|
2017-01-17 14:06:33 +00:00
|
|
|
* Copyright (C) 2013-2017 CERN
|
2022-09-11 21:17:45 +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
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __PNS_ITEM_H
|
|
|
|
#define __PNS_ITEM_H
|
|
|
|
|
2016-08-30 15:28:35 +00:00
|
|
|
#include <memory>
|
2022-08-30 12:52:34 +00:00
|
|
|
#include <unordered_set>
|
2013-09-18 17:55:16 +00:00
|
|
|
#include <math/vector2d.h>
|
|
|
|
|
|
|
|
#include <geometry/shape.h>
|
|
|
|
#include <geometry/shape_line_chain.h>
|
|
|
|
|
|
|
|
#include "pns_layerset.h"
|
|
|
|
|
2020-10-17 12:52:18 +00:00
|
|
|
class BOARD_ITEM;
|
2016-08-29 14:38:11 +00:00
|
|
|
|
|
|
|
namespace PNS {
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
class NODE;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
enum LineMarker {
|
|
|
|
MK_HEAD = ( 1 << 0 ),
|
|
|
|
MK_VIOLATION = ( 1 << 3 ),
|
2015-02-18 00:29:54 +00:00
|
|
|
MK_LOCKED = ( 1 << 4 ),
|
2022-08-15 13:31:43 +00:00
|
|
|
MK_DP_COUPLED = ( 1 << 5 )
|
2014-05-14 13:53:54 +00:00
|
|
|
};
|
|
|
|
|
2022-08-15 13:31:43 +00:00
|
|
|
|
2022-08-30 12:52:34 +00:00
|
|
|
class ITEM;
|
|
|
|
class HOLE;
|
|
|
|
struct COLLISION_SEARCH_CONTEXT;
|
2022-08-15 13:31:43 +00:00
|
|
|
|
2022-08-29 20:21:46 +00:00
|
|
|
class ITEM_OWNER {};
|
|
|
|
|
|
|
|
class OWNABLE_ITEM
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
OWNABLE_ITEM() :
|
|
|
|
m_owner( nullptr )
|
|
|
|
{}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the owner of this item, or NULL if there's none.
|
|
|
|
*/
|
|
|
|
const ITEM_OWNER* Owner() const { return m_owner; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the node that owns this item. An item can belong to a single NODE or be unowned.
|
|
|
|
*/
|
|
|
|
void SetOwner( const ITEM_OWNER* aOwner ) { m_owner = aOwner; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return true if the item is owned by the node aNode.
|
|
|
|
*/
|
|
|
|
bool BelongsTo( const ITEM_OWNER* aNode ) const
|
|
|
|
{
|
|
|
|
return m_owner == aNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
const ITEM_OWNER *m_owner;
|
|
|
|
};
|
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Base class for PNS router board items.
|
2013-09-18 17:55:16 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* Implements the shared properties of all PCB items net, spanned layers, geometric shape and
|
|
|
|
* reference to owning model.
|
2013-09-18 17:55:16 +00:00
|
|
|
*/
|
2022-08-29 20:21:46 +00:00
|
|
|
class ITEM : public OWNABLE_ITEM, public ITEM_OWNER
|
2013-09-18 17:55:16 +00:00
|
|
|
{
|
|
|
|
public:
|
2013-09-26 21:53:54 +00:00
|
|
|
static const int UnusedNet = INT_MAX;
|
|
|
|
|
2021-01-27 22:15:38 +00:00
|
|
|
///< Supported item types
|
2013-09-26 21:53:54 +00:00
|
|
|
enum PnsKind
|
|
|
|
{
|
2016-08-29 16:11:42 +00:00
|
|
|
SOLID_T = 1,
|
|
|
|
LINE_T = 2,
|
|
|
|
JOINT_T = 4,
|
|
|
|
SEGMENT_T = 8,
|
2019-05-17 00:13:21 +00:00
|
|
|
ARC_T = 16,
|
|
|
|
VIA_T = 32,
|
|
|
|
DIFF_PAIR_T = 64,
|
2022-08-30 12:52:34 +00:00
|
|
|
HOLE_T = 128,
|
|
|
|
ANY_T = 0xffff
|
2013-09-26 21:53:54 +00:00
|
|
|
};
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
ITEM( PnsKind aKind )
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
|
|
|
m_net = UnusedNet;
|
|
|
|
m_movable = true;
|
|
|
|
m_kind = aKind;
|
2021-07-19 23:56:05 +00:00
|
|
|
m_parent = nullptr;
|
|
|
|
m_owner = nullptr;
|
2014-05-14 13:53:54 +00:00
|
|
|
m_marker = 0;
|
|
|
|
m_rank = -1;
|
2018-02-03 09:39:46 +00:00
|
|
|
m_routable = true;
|
2021-06-03 20:30:00 +00:00
|
|
|
m_isVirtual = false;
|
2022-09-05 18:44:41 +00:00
|
|
|
m_isFreePad = false;
|
2021-11-25 23:41:47 +00:00
|
|
|
m_isCompoundShapePrimitive = false;
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
ITEM( const ITEM& aOther )
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
|
|
|
m_layers = aOther.m_layers;
|
|
|
|
m_net = aOther.m_net;
|
|
|
|
m_movable = aOther.m_movable;
|
|
|
|
m_kind = aOther.m_kind;
|
|
|
|
m_parent = aOther.m_parent;
|
2019-08-07 21:45:38 +00:00
|
|
|
m_owner = aOther.m_owner; // fixme: wtf this was null?
|
2014-05-14 13:53:54 +00:00
|
|
|
m_marker = aOther.m_marker;
|
|
|
|
m_rank = aOther.m_rank;
|
2018-02-03 09:39:46 +00:00
|
|
|
m_routable = aOther.m_routable;
|
2021-06-03 20:30:00 +00:00
|
|
|
m_isVirtual = aOther.m_isVirtual;
|
2022-09-05 18:44:41 +00:00
|
|
|
m_isFreePad = aOther.m_isFreePad;
|
2021-11-25 23:41:47 +00:00
|
|
|
m_isCompoundShapePrimitive = aOther.m_isCompoundShapePrimitive;
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
|
|
|
|
2016-08-29 17:31:13 +00:00
|
|
|
virtual ~ITEM();
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Return a deep copy of the item.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
virtual ITEM* Clone() const = 0;
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/*
|
2021-01-27 22:15:38 +00:00
|
|
|
* Returns a convex polygon "hull" of a the item, that is used as the walk-around path.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
|
|
|
* @param aClearance defines how far from the body of the item the hull should be,
|
|
|
|
* @param aWalkaroundThickness is the width of the line that walks around this hull.
|
|
|
|
*/
|
2021-01-04 18:06:39 +00:00
|
|
|
virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0,
|
|
|
|
int aLayer = -1 ) const
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
|
|
|
return SHAPE_LINE_CHAIN();
|
2014-05-16 11:37:31 +00:00
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Return the type (kind) of the item.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2014-11-02 16:25:04 +00:00
|
|
|
PnsKind Kind() const
|
|
|
|
{
|
2014-05-14 13:53:54 +00:00
|
|
|
return m_kind;
|
|
|
|
}
|
2014-11-02 16:25:04 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2023-04-06 16:59:43 +00:00
|
|
|
* @return true if the item's type matches the mask \a aKindMask.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2014-11-02 16:25:04 +00:00
|
|
|
bool OfKind( int aKindMask ) const
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
2014-05-16 11:37:31 +00:00
|
|
|
return ( aKindMask & m_kind ) != 0;
|
2014-05-14 13:53:54 +00:00
|
|
|
}
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2023-04-06 16:59:43 +00:00
|
|
|
* @return the kind of the item, as string
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2019-07-21 22:35:41 +00:00
|
|
|
std::string KindStr() const;
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2020-10-17 12:52:18 +00:00
|
|
|
void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; }
|
2023-04-06 16:59:43 +00:00
|
|
|
BOARD_ITEM* Parent() const { return m_parent; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the BOARD_ITEM, even if it's not the direct parent.
|
|
|
|
*/
|
|
|
|
virtual BOARD_ITEM* BoardItem() const { return m_parent; }
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2019-07-21 22:35:41 +00:00
|
|
|
void SetNet( int aNet ) { m_net = aNet; }
|
|
|
|
int Net() const { return m_net; }
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2019-07-21 22:35:41 +00:00
|
|
|
const LAYER_RANGE& Layers() const { return m_layers; }
|
|
|
|
void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2019-07-21 22:35:41 +00:00
|
|
|
void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
|
|
|
|
virtual int Layer() const { return Layers().Start(); }
|
2014-05-14 13:53:54 +00:00
|
|
|
|
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Return true if the set of layers spanned by aOther overlaps our layers.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2016-08-29 17:31:13 +00:00
|
|
|
bool LayersOverlap( const ITEM* aOther ) const
|
2014-05-14 13:53:54 +00:00
|
|
|
{
|
|
|
|
return Layers().Overlaps( aOther->Layers() );
|
|
|
|
}
|
2022-08-30 12:52:34 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Check for a collision (clearance violation) with between us and item \a aOther.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* Collision checking takes all PCB stuff into account (layers, nets, DRC rules).
|
2019-07-21 22:35:41 +00:00
|
|
|
* Optionally returns a minimum translation vector for force propagation algorithm.
|
2014-05-14 13:53:54 +00:00
|
|
|
*
|
2021-01-27 22:15:38 +00:00
|
|
|
* @param aOther is the item to check collision against.
|
2014-11-02 16:25:04 +00:00
|
|
|
* @return true, if a collision was found.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
2022-08-30 12:52:34 +00:00
|
|
|
bool Collide( const ITEM* aHead, const NODE* aNode,
|
|
|
|
COLLISION_SEARCH_CONTEXT* aCtx = nullptr ) const;
|
2013-09-26 21:53:54 +00:00
|
|
|
|
2014-05-14 13:53:54 +00:00
|
|
|
/**
|
2021-01-27 22:15:38 +00:00
|
|
|
* Return the geometrical shape of the item. Used for collision detection and spatial indexing.
|
2014-05-14 13:53:54 +00:00
|
|
|
*/
|
|
|
|
virtual const SHAPE* Shape() const
|
2013-09-26 21:53:54 +00:00
|
|
|
{
|
2021-01-01 00:29:05 +00:00
|
|
|
return nullptr;
|
2013-09-26 21:53:54 +00:00
|
|
|
}
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2020-10-05 23:07:34 +00:00
|
|
|
virtual void Mark( int aMarker ) const { m_marker = aMarker; }
|
2020-10-05 19:54:12 +00:00
|
|
|
virtual void Unmark( int aMarker = -1 ) const { m_marker &= ~aMarker; }
|
2019-07-21 22:35:41 +00:00
|
|
|
virtual int Marker() const { return m_marker; }
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2019-07-21 22:35:41 +00:00
|
|
|
virtual void SetRank( int aRank ) { m_rank = aRank; }
|
|
|
|
virtual int Rank() const { return m_rank; }
|
2014-05-14 13:53:54 +00:00
|
|
|
|
2014-05-16 11:37:31 +00:00
|
|
|
virtual VECTOR2I Anchor( int n ) const
|
2014-11-02 16:25:04 +00:00
|
|
|
{
|
2016-08-15 15:16:53 +00:00
|
|
|
return VECTOR2I();
|
2014-05-16 11:37:31 +00:00
|
|
|
}
|
2014-11-02 16:25:04 +00:00
|
|
|
|
|
|
|
virtual int AnchorCount() const
|
|
|
|
{
|
|
|
|
return 0;
|
2014-05-14 13:53:54 +00:00
|
|
|
}
|
|
|
|
|
2016-08-15 15:16:50 +00:00
|
|
|
bool IsLocked() const
|
|
|
|
{
|
|
|
|
return Marker() & MK_LOCKED;
|
|
|
|
}
|
|
|
|
|
2019-07-21 22:35:41 +00:00
|
|
|
void SetRoutable( bool aRoutable ) { m_routable = aRoutable; }
|
|
|
|
bool IsRoutable() const { return m_routable; }
|
2018-02-03 09:39:46 +00:00
|
|
|
|
2022-09-05 18:44:41 +00:00
|
|
|
void SetIsFreePad( bool aIsFreePad = true ) { m_isFreePad = aIsFreePad; }
|
|
|
|
bool IsFreePad() const { return m_isFreePad; }
|
|
|
|
|
2021-06-03 20:30:00 +00:00
|
|
|
bool IsVirtual() const
|
|
|
|
{
|
|
|
|
return m_isVirtual;
|
|
|
|
}
|
|
|
|
|
2021-11-25 23:41:47 +00:00
|
|
|
void SetIsCompoundShapePrimitive() { m_isCompoundShapePrimitive = true; }
|
|
|
|
bool IsCompoundShapePrimitive() const { return m_isCompoundShapePrimitive; }
|
|
|
|
|
2022-08-30 12:52:34 +00:00
|
|
|
virtual bool HasHole() const { return false; }
|
|
|
|
virtual HOLE *Hole() const { return nullptr; }
|
|
|
|
virtual void SetHole( HOLE* aHole ) {};
|
|
|
|
|
2022-10-23 22:34:42 +00:00
|
|
|
virtual const std::string Format() const;
|
|
|
|
|
2013-09-18 17:55:16 +00:00
|
|
|
private:
|
2022-08-30 12:52:34 +00:00
|
|
|
bool collideSimple( const ITEM* aHead, const NODE* aNode,
|
|
|
|
COLLISION_SEARCH_CONTEXT* aCtx ) const;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
|
|
|
protected:
|
2020-10-17 12:52:18 +00:00
|
|
|
PnsKind m_kind;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2020-10-17 12:52:18 +00:00
|
|
|
BOARD_ITEM* m_parent;
|
|
|
|
LAYER_RANGE m_layers;
|
2013-09-18 17:55:16 +00:00
|
|
|
|
2020-10-17 12:52:18 +00:00
|
|
|
bool m_movable;
|
|
|
|
int m_net;
|
|
|
|
mutable int m_marker;
|
|
|
|
int m_rank;
|
|
|
|
bool m_routable;
|
2021-06-03 20:30:00 +00:00
|
|
|
bool m_isVirtual;
|
2022-09-05 18:44:41 +00:00
|
|
|
bool m_isFreePad;
|
2021-11-25 23:41:47 +00:00
|
|
|
bool m_isCompoundShapePrimitive;
|
2013-09-18 17:55:16 +00:00
|
|
|
};
|
|
|
|
|
2020-11-24 22:16:41 +00:00
|
|
|
template<typename T, typename S>
|
|
|
|
std::unique_ptr<T> ItemCast( std::unique_ptr<S> aPtr )
|
2016-08-30 15:28:35 +00:00
|
|
|
{
|
2020-11-24 22:16:41 +00:00
|
|
|
static_assert( std::is_base_of<ITEM, S>::value, "Need to be handed a ITEM!" );
|
|
|
|
static_assert( std::is_base_of<ITEM, T>::value, "Need to cast to an ITEM!" );
|
|
|
|
return std::unique_ptr<T>( static_cast<T*>( aPtr.release() ) );
|
2016-08-30 15:28:35 +00:00
|
|
|
}
|
|
|
|
|
2020-11-24 22:16:41 +00:00
|
|
|
template<typename T>
|
|
|
|
std::unique_ptr< typename std::remove_const<T>::type > Clone( const T& aItem )
|
2016-08-30 15:28:35 +00:00
|
|
|
{
|
2020-11-24 22:16:41 +00:00
|
|
|
static_assert( std::is_base_of<ITEM, T>::value, "Need to be handed an ITEM!" );
|
|
|
|
return std::unique_ptr<typename std::remove_const<T>::type>( aItem.Clone() );
|
2016-08-30 15:28:35 +00:00
|
|
|
}
|
|
|
|
|
2016-08-29 14:38:11 +00:00
|
|
|
}
|
|
|
|
|
2013-10-14 14:13:35 +00:00
|
|
|
#endif // __PNS_ITEM_H
|