Horizon
Loading...
Searching...
No Matches
pns_joint.h
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2014 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_JOINT_H
24#define __PNS_JOINT_H
25
26#include <vector>
27
28#include <math/vector2d.h>
29
30#include "pns_item.h"
31#include "pns_segment.h"
32#include "pns_itemset.h"
33
34namespace PNS {
35
42class JOINT : public ITEM
43{
44public:
45 typedef ITEM_SET::ENTRIES LINKED_ITEMS;
46
49 struct HASH_TAG
50 {
51 VECTOR2I pos;
52 int net;
53 };
54
56 {
57 std::size_t operator()( const JOINT::HASH_TAG& aP ) const
58 {
59 using std::size_t;
60 using std::hash;
61 using std::string;
62
63 return ( (hash<int>()( aP.pos.x )
64 ^ (hash<int>()( aP.pos.y ) << 1) ) >> 1 )
65 ^ (hash<int>()( aP.net ) << 1);
66 }
67 };
68
69 JOINT() :
70 ITEM( JOINT_T ), m_tag(), m_locked( false ) {}
71
72 JOINT( const VECTOR2I& aPos, const LAYER_RANGE& aLayers, int aNet = -1 ) :
73 ITEM( JOINT_T )
74 {
75 m_tag.pos = aPos;
76 m_tag.net = aNet;
77 m_layers = aLayers;
78 m_locked = false;
79 }
80
81 JOINT( const JOINT& aB ) :
82 ITEM( JOINT_T )
83 {
84 m_layers = aB.m_layers;
85 m_tag.pos = aB.m_tag.pos;
86 m_tag.net = aB.m_tag.net;
87 m_linkedItems = aB.m_linkedItems;
88 m_layers = aB.m_layers;
89 m_locked = aB.m_locked;
90 }
91
92 ITEM* Clone( ) const override
93 {
94 assert( false );
95 return nullptr;
96 }
97
103 bool IsLineCorner( bool aAllowLockedSegs = false ) const
104 {
105 if( m_linkedItems.Size() != 2 || m_linkedItems.Count( SEGMENT_T | ARC_T ) != 2 )
106 {
107 if( !aAllowLockedSegs )
108 {
109 return false;
110 }
111 else if( m_linkedItems.Size() == 3
112 && m_linkedItems.Count( SEGMENT_T | ARC_T ) == 2
113 && m_linkedItems.Count( VIA_T ) == 1 )
114 {
115 assert( static_cast<const ITEM*>( m_linkedItems[2] )->Kind() == VIA_T );
116
117 const VIA* via = static_cast<const VIA*>( m_linkedItems[2] );
118
119 if( !via->IsVirtual() )
120 return false;
121 }
122 else
123 {
124 return false;
125 }
126 }
127
128 auto seg1 = static_cast<LINKED_ITEM*>( m_linkedItems[0] );
129 auto seg2 = static_cast<LINKED_ITEM*>( m_linkedItems[1] );
130
131 // joints between segments of different widths are not considered trivial.
132 return seg1->Width() == seg2->Width();
133 }
134
135 bool IsNonFanoutVia() const
136 {
137 int vias = m_linkedItems.Count( VIA_T );
138 int segs = m_linkedItems.Count( SEGMENT_T );
139 segs += m_linkedItems.Count( ARC_T );
140
141 return ( m_linkedItems.Size() == 3 && vias == 1 && segs == 2 );
142 }
143
144 bool IsStitchingVia() const
145 {
146 return ( m_linkedItems.Size() == 1 && m_linkedItems.Count( VIA_T ) == 1 );
147 }
148
150 {
151 if( m_linkedItems.Size() != 2 )
152 return false;
153
154 if( m_linkedItems.Count( SEGMENT_T ) != 2)
155 return false;
156
157 SEGMENT* seg1 = static_cast<SEGMENT*>( m_linkedItems[0] );
158 SEGMENT* seg2 = static_cast<SEGMENT*>( m_linkedItems[1] );
159
160 return seg1->Width() != seg2->Width();
161 }
162
164 void Link( ITEM* aItem )
165 {
166 if( m_linkedItems.Contains( aItem ) )
167 return;
168
169 m_linkedItems.Add( aItem );
170 }
171
174 bool Unlink( ITEM* aItem )
175 {
176 m_linkedItems.Erase( aItem );
177 return m_linkedItems.Size() == 0;
178 }
179
182 LINKED_ITEM* NextSegment( ITEM* aCurrent, bool aAllowLockedSegs = false ) const
183 {
184 if( !IsLineCorner( aAllowLockedSegs ) )
185 return nullptr;
186
187 return static_cast<LINKED_ITEM*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
188 }
189
190 VIA* Via()
191 {
192 for( ITEM* item : m_linkedItems.Items() )
193 {
194 if( item->OfKind( VIA_T ) )
195 return static_cast<VIA*>( item );
196 }
197
198 return nullptr;
199 }
200
201
203 const HASH_TAG& Tag() const
204 {
205 return m_tag;
206 }
207
208 const VECTOR2I& Pos() const
209 {
210 return m_tag.pos;
211 }
212
213 int Net() const
214 {
215 return m_tag.net;
216 }
217
218 const LINKED_ITEMS& LinkList() const
219 {
220 return m_linkedItems.CItems();
221 }
222
223 const ITEM_SET& CLinks() const
224 {
225 return m_linkedItems;
226 }
227
228 ITEM_SET& Links()
229 {
230 return m_linkedItems;
231 }
232
233 int LinkCount( int aMask = -1 ) const
234 {
235 return m_linkedItems.Count( aMask );
236 }
237
238 void Dump() const;
239
240 bool operator==( const JOINT& rhs ) const
241 {
242 return m_tag.pos == rhs.m_tag.pos && m_tag.net == rhs.m_tag.net;
243 }
244
245 void Merge( const JOINT& aJoint )
246 {
247 if( !Overlaps( aJoint ) )
248 return;
249
250 m_layers.Merge( aJoint.m_layers );
251
252 if( aJoint.IsLocked() )
253 m_locked = true;
254
255 for( ITEM* item : aJoint.LinkList() )
256 {
257 m_linkedItems.Add( item );
258 }
259 }
260
261 bool Overlaps( const JOINT& rhs ) const
262 {
263 return m_tag.pos == rhs.m_tag.pos &&
264 m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
265 }
266
267 void Lock( bool aLock = true )
268 {
269 m_locked = aLock;
270 }
271
272 bool IsLocked() const
273 {
274 return m_locked;
275 }
276
277private:
279 HASH_TAG m_tag;
280
282 ITEM_SET m_linkedItems;
283
285 bool m_locked;
286};
287
288inline bool operator==( JOINT::HASH_TAG const& aP1, JOINT::HASH_TAG const& aP2 )
289{
290 return aP1.pos == aP2.pos && aP1.net == aP2.net;
291}
292
293}
294
295#endif // __PNS_JOINT_H
Represent a contiguous set of PCB layers.
Definition pns_layerset.h:32
void Merge(const LAYER_RANGE &aOther)
Shortcut for comparisons/overlap tests.
Definition pns_layerset.h:92
Base class for PNS router board items.
Definition pns_item.h:57
PnsKind Kind() const
Return the type (kind) of the item.
Definition pns_item.h:131
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition pns_joint.h:43
ITEM_SET::ENTRIES LINKED_ITEMS
Joints are hashed by their position, layers and net.
Definition pns_joint.h:45
bool IsLineCorner(bool aAllowLockedSegs=false) const
Checks if a joint connects two segments of the same net, layer, and width.
Definition pns_joint.h:103
const HASH_TAG & Tag() const
trivial accessors
Definition pns_joint.h:203
void Link(ITEM *aItem)
Unlink a given board item from the joint (upon its removal from a NODE)
Definition pns_joint.h:164
ITEM * Clone() const override
Return a deep copy of the item.
Definition pns_joint.h:92
bool IsTraceWidthChange() const
Link the joint to a given board item (when it's added to the NODE).
Definition pns_joint.h:149
bool Unlink(ITEM *aItem)
For trivial joints, return the segment adjacent to (aCurrent).
Definition pns_joint.h:174
Definition pns_linked_item.h:30
Definition pns_segment.h:39
Definition pns_via.h:49
Definition pns_joint.h:50
Definition pns_joint.h:56