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