1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2017 CERN
5  * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
8  *
9  * This program is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation, either version 3 of the License, or (at your
12  * option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #ifndef __PNS_ITEM_H
24 #define __PNS_ITEM_H
25 
26 #include <memory>
27 #include <math/vector2d.h>
28 
29 #include <geometry/shape.h>
30 #include <geometry/shape_line_chain.h>
31 
32 #include "pns_layerset.h"
33 
34 class BOARD_ITEM;
35 
36 namespace PNS {
37 
38 class NODE;
39 
40 enum LineMarker {
41     MK_HEAD         = ( 1 << 0 ),
42     MK_VIOLATION    = ( 1 << 3 ),
43     MK_LOCKED       = ( 1 << 4 ),
44     MK_DP_COUPLED   = ( 1 << 5 ),
45     MK_HOLE         = ( 1 << 6 )
46 };
47 
48 
49 /**
50  * Base class for PNS router board items.
51  *
52  * Implements the shared properties of all PCB items  net, spanned layers, geometric shape and
53  * reference to owning model.
54  */
55 class ITEM
56 {
57 public:
58     static const int UnusedNet = INT_MAX;
59 
60     ///< Supported item types
61     enum PnsKind
62     {
63         SOLID_T     =    1,
64         LINE_T      =    2,
65         JOINT_T     =    4,
66         SEGMENT_T   =    8,
67         ARC_T       =   16,
68         VIA_T       =   32,
69         DIFF_PAIR_T =   64,
70         ANY_T       =   0xff
71     };
72 
ITEM(PnsKind aKind)73     ITEM( PnsKind aKind )
74     {
75         m_net = UnusedNet;
76         m_movable = true;
77         m_kind = aKind;
78         m_parent = nullptr;
79         m_owner = nullptr;
80         m_marker = 0;
81         m_rank = -1;
82         m_routable = true;
83         m_isVirtual = false;
84         m_isCompoundShapePrimitive = false;
85     }
86 
ITEM(const ITEM & aOther)87     ITEM( const ITEM& aOther )
88     {
89         m_layers = aOther.m_layers;
90         m_net = aOther.m_net;
91         m_movable = aOther.m_movable;
92         m_kind = aOther.m_kind;
93         m_parent = aOther.m_parent;
94         m_owner = aOther.m_owner; // fixme: wtf this was null?
95         m_marker = aOther.m_marker;
96         m_rank = aOther.m_rank;
97         m_routable = aOther.m_routable;
98         m_isVirtual = aOther.m_isVirtual;
99         m_isCompoundShapePrimitive = aOther.m_isCompoundShapePrimitive;
100     }
101 
102     virtual ~ITEM();
103 
104     /**
105      * Return a deep copy of the item.
106      */
107     virtual ITEM* Clone() const = 0;
108 
109     /*
110      * Returns a convex polygon "hull" of a the item, that is used as the walk-around path.
111      *
112      * @param aClearance defines how far from the body of the item the hull should be,
113      * @param aWalkaroundThickness is the width of the line that walks around this hull.
114      */
115     virtual const SHAPE_LINE_CHAIN Hull( int aClearance = 0, int aWalkaroundThickness = 0,
116                                          int aLayer = -1 ) const
117     {
118         return SHAPE_LINE_CHAIN();
119     }
120 
HoleHull(int aClearance,int aWalkaroundThickness,int aLayer)121     virtual const SHAPE_LINE_CHAIN HoleHull( int aClearance, int aWalkaroundThickness,
122                                              int aLayer ) const
123     {
124         return SHAPE_LINE_CHAIN();
125     }
126 
127     /**
128      * Return the type (kind) of the item.
129      */
Kind()130     PnsKind Kind() const
131     {
132         return m_kind;
133     }
134 
135     /**
136      * Return true if the item's type matches the mask \a aKindMask.
137      */
OfKind(int aKindMask)138     bool OfKind( int aKindMask ) const
139     {
140         return ( aKindMask & m_kind ) != 0;
141     }
142 
143     /**
144      * Returns the kind of the item, as string
145      */
146     std::string KindStr() const;
147 
SetParent(BOARD_ITEM * aParent)148     void SetParent( BOARD_ITEM* aParent ) { m_parent = aParent; }
Parent()149     BOARD_ITEM* Parent() const { return m_parent; }
150 
SetNet(int aNet)151     void SetNet( int aNet ) { m_net = aNet; }
Net()152     int Net() const { return m_net;  }
153 
Layers()154     const LAYER_RANGE& Layers() const { return m_layers; }
SetLayers(const LAYER_RANGE & aLayers)155     void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
156 
SetLayer(int aLayer)157     void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
Layer()158     virtual int Layer() const { return Layers().Start(); }
159 
160     /**
161      * Return true if the set of layers spanned by aOther overlaps our layers.
162      */
LayersOverlap(const ITEM * aOther)163     bool LayersOverlap( const ITEM* aOther ) const
164     {
165         return Layers().Overlaps( aOther->Layers() );
166     }
167 
168     /**
169      * Return the owner of this item, or NULL if there's none.
170      */
Owner()171     NODE* Owner() const { return m_owner; }
172 
173     /**
174      * Set the node that owns this item. An item can belong to a single NODE or be unowned.
175      */
SetOwner(NODE * aOwner)176     void SetOwner( NODE* aOwner ) { m_owner = aOwner; }
177 
178     /**
179      * @return true if the item is owned by the node aNode.
180      */
BelongsTo(NODE * aNode)181     bool BelongsTo( NODE* aNode ) const
182     {
183         return m_owner == aNode;
184     }
185 
186     /**
187      * Check for a collision (clearance violation) with between us and item \a aOther.
188      *
189      * Collision checking takes all PCB stuff into account (layers, nets, DRC rules).
190      * Optionally returns a minimum translation vector for force propagation algorithm.
191      *
192      * @param aOther is the item to check collision against.
193      * @return true, if a collision was found.
194      */
195     bool Collide( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly = true ) const;
196 
197     /**
198      * Return the geometrical shape of the item. Used for collision detection and spatial indexing.
199      */
Shape()200     virtual const SHAPE* Shape() const
201     {
202         return nullptr;
203     }
204 
Hole()205     virtual const SHAPE* Hole() const
206     {
207         return nullptr;
208     }
209 
Mark(int aMarker)210     virtual void Mark( int aMarker ) const { m_marker = aMarker; }
211     virtual void Unmark( int aMarker = -1 ) const { m_marker &= ~aMarker; }
Marker()212     virtual int Marker() const { return m_marker; }
213 
SetRank(int aRank)214     virtual void SetRank( int aRank ) { m_rank = aRank; }
Rank()215     virtual int Rank() const { return m_rank; }
216 
Anchor(int n)217     virtual VECTOR2I Anchor( int n ) const
218     {
219         return VECTOR2I();
220     }
221 
AnchorCount()222     virtual int AnchorCount() const
223     {
224         return 0;
225     }
226 
IsLocked()227     bool IsLocked() const
228     {
229         return Marker() & MK_LOCKED;
230     }
231 
SetRoutable(bool aRoutable)232     void SetRoutable( bool aRoutable ) { m_routable = aRoutable; }
IsRoutable()233     bool IsRoutable() const { return m_routable; }
234 
IsVirtual()235     bool IsVirtual() const
236     {
237         return m_isVirtual;
238     }
239 
SetIsCompoundShapePrimitive()240     void SetIsCompoundShapePrimitive() { m_isCompoundShapePrimitive = true; }
IsCompoundShapePrimitive()241     bool IsCompoundShapePrimitive() const { return m_isCompoundShapePrimitive; }
242 
243 private:
244     bool collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly ) const;
245 
246 protected:
247     PnsKind       m_kind;
248 
249     BOARD_ITEM*   m_parent;
250     NODE*         m_owner;
251     LAYER_RANGE   m_layers;
252 
253     bool          m_movable;
254     int           m_net;
255     mutable int   m_marker;
256     int           m_rank;
257     bool          m_routable;
258     bool          m_isVirtual;
259     bool          m_isCompoundShapePrimitive;
260 };
261 
262 template<typename T, typename S>
ItemCast(std::unique_ptr<S> aPtr)263 std::unique_ptr<T> ItemCast( std::unique_ptr<S> aPtr )
264 {
265     static_assert( std::is_base_of<ITEM, S>::value, "Need to be handed a ITEM!" );
266     static_assert( std::is_base_of<ITEM, T>::value, "Need to cast to an ITEM!" );
267     return std::unique_ptr<T>( static_cast<T*>( aPtr.release() ) );
268 }
269 
270 template<typename T>
Clone(const T & aItem)271 std::unique_ptr< typename std::remove_const<T>::type > Clone( const T& aItem )
272 {
273     static_assert( std::is_base_of<ITEM, T>::value, "Need to be handed an ITEM!" );
274     return std::unique_ptr<typename std::remove_const<T>::type>( aItem.Clone() );
275 }
276 
277 }
278 
279 #endif    // __PNS_ITEM_H
280