KiCad PCB EDA Suite
connectivity_items.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2016-2018 CERN
5  * Copyright (C) 2019 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
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
28 
30 {
31  if( !m_valid )
32  return 0;
33 
34  return m_parent->Type() == PCB_TRACE_T ? 2 : 1;
35 }
36 
37 
38 const VECTOR2I CN_ITEM::GetAnchor( int n ) const
39 {
40  if( !m_valid )
41  return VECTOR2I();
42 
43  switch( m_parent->Type() )
44  {
45  case PCB_PAD_T:
46  return static_cast<const D_PAD*>( m_parent )->ShapePos();
47  break;
48 
49  case PCB_TRACE_T:
50  {
51  auto tr = static_cast<const TRACK*>( m_parent );
52  return ( n == 0 ? tr->GetStart() : tr->GetEnd() );
53 
54  break;
55  }
56 
57  case PCB_VIA_T:
58  return static_cast<const VIA*>( m_parent )->GetStart();
59 
60  default:
61  assert( false );
62  return VECTOR2I();
63  }
64 }
65 
66 
67 int CN_ITEM::Net() const
68 {
69  if( !m_parent || !m_valid )
70  return -1;
71 
72  return m_parent->GetNetCode();
73 }
74 
75 
77 {
78  printf(" valid: %d, connected: \n", !!Valid());
79 
80  for( auto i : m_connected )
81  {
82  TRACK* t = static_cast<TRACK*>( i->Parent() );
83  printf( " - %p %d\n", t, t->Type() );
84  }
85 }
86 
87 
89 {
90  if( !Valid() )
91  return 0;
92 
93  const auto zone = static_cast<const ZONE_CONTAINER*>( Parent() );
94  const auto& outline = zone->GetFilledPolysList().COutline( m_subpolyIndex );
95 
96  return outline.PointCount() ? 1 : 0;
97 }
98 
99 
100 const VECTOR2I CN_ZONE::GetAnchor( int n ) const
101 {
102  if( !Valid() )
103  return VECTOR2I();
104 
105  const auto zone = static_cast<const ZONE_CONTAINER*> ( Parent() );
106  const auto& outline = zone->GetFilledPolysList().COutline( m_subpolyIndex );
107 
108  return outline.CPoint( 0 );
109 }
110 
111 
113 {
114  for( auto it = m_connected.begin(); it != m_connected.end(); )
115  {
116  if( !(*it)->Valid() )
117  it = m_connected.erase( it );
118  else
119  ++it;
120  }
121 }
122 
123 
125  {
126  if( !pad->IsOnCopperLayer() )
127  return nullptr;
128 
129  auto item = new CN_ITEM( pad, false, 1 );
130  item->AddAnchor( pad->ShapePos() );
131  item->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
132 
133  switch( pad->GetAttribute() )
134  {
135  case PAD_ATTRIB_SMD:
137  case PAD_ATTRIB_CONN:
138  {
139  LSET lmsk = pad->GetLayerSet();
140 
141  for( int i = 0; i <= MAX_CU_LAYERS; i++ )
142  {
143  if( lmsk[i] )
144  {
145  item->SetLayer( i );
146  break;
147  }
148  }
149  break;
150  }
151  default:
152  break;
153  }
154 
155  addItemtoTree( item );
156  m_items.push_back( item );
157  SetDirty();
158  return item;
159 }
160 
162  {
163  auto item = new CN_ITEM( track, true );
164  m_items.push_back( item );
165  item->AddAnchor( track->GetStart() );
166  item->AddAnchor( track->GetEnd() );
167  item->SetLayer( track->GetLayer() );
168  addItemtoTree( item );
169  SetDirty();
170  return item;
171  }
172 
174  {
175  auto item = new CN_ITEM( via, true, 1 );
176 
177  m_items.push_back( item );
178  item->AddAnchor( via->GetStart() );
179  item->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) );
180  addItemtoTree( item );
181  SetDirty();
182  return item;
183  }
184 
185  const std::vector<CN_ITEM*> CN_LIST::Add( ZONE_CONTAINER* zone )
186  {
187  const auto& polys = zone->GetFilledPolysList();
188 
189  std::vector<CN_ITEM*> rv;
190 
191  for( int j = 0; j < polys.OutlineCount(); j++ )
192  {
193  CN_ZONE* zitem = new CN_ZONE( zone, false, j );
194  const auto& outline = zone->GetFilledPolysList().COutline( j );
195 
196  for( int k = 0; k < outline.PointCount(); k++ )
197  zitem->AddAnchor( outline.CPoint( k ) );
198 
199  m_items.push_back( zitem );
200  zitem->SetLayer( zone->GetLayer() );
201  addItemtoTree( zitem );
202  rv.push_back( zitem );
203  SetDirty();
204  }
205 
206  return rv;
207  }
208 
209 
210 void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
211 {
212  if( !m_hasInvalid )
213  return;
214 
215  auto lastItem = std::remove_if(m_items.begin(), m_items.end(), [&aGarbage] ( CN_ITEM* item )
216  {
217  if( !item->Valid() )
218  {
219  aGarbage.push_back ( item );
220  return true;
221  }
222 
223  return false;
224  } );
225 
226  m_items.resize( lastItem - m_items.begin() );
227 
228  for( auto item : m_items )
229  item->RemoveInvalidRefs();
230 
231  for( auto item : aGarbage )
232  m_index.Remove( item );
233 
234  m_hasInvalid = false;
235 }
236 
237 
239 {
240  assert( m_item->Valid() );
241  return m_item->Parent();
242 }
243 
244 
245 bool CN_ANCHOR::Valid() const
246 {
247  if( !m_item )
248  return false;
249 
250  return m_item->Valid();
251 }
252 
253 
255 {
256  if( !m_cluster )
257  return true;
258 
259  // the minimal number of items connected to item_ref
260  // at this anchor point to decide the anchor is *not* dangling
261  size_t minimal_count = 1;
262  size_t connected_count = m_item->ConnectedItems().size();
263 
264  // a via can be removed if connected to only one other item.
265  if( Parent()->Type() == PCB_VIA_T )
266  return connected_count < 2;
267 
268  if( m_item->AnchorCount() == 1 )
269  return connected_count < minimal_count;
270 
271  // Items with multiple anchors have usually items connected to each anchor.
272  // We want only the item count of this anchor point
273  connected_count = 0;
274  for( auto item : m_item->ConnectedItems() )
275  {
276  if( item->Parent()->Type() == PCB_ZONE_AREA_T )
277  {
278  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item->Parent() );
279 
280  if( zone->HitTestFilledArea( wxPoint( Pos().x, Pos().y ) ) )
281  connected_count++;
282  }
283  else if( item->Parent()->HitTest( wxPoint( Pos().x, Pos().y ) ) )
284  connected_count++;
285  }
286 
287  return connected_count < minimal_count;
288 }
289 
290 
292 {
293  if( !m_cluster )
294  return 0;
295 
296  int connected_count = 0;
297 
298  for( auto item : m_item->ConnectedItems() )
299  {
300  if( item->Parent()->Type() == PCB_ZONE_AREA_T )
301  {
302  ZONE_CONTAINER* zone = static_cast<ZONE_CONTAINER*>( item->Parent() );
303 
304  if( zone->HitTestFilledArea( wxPoint( Pos().x, Pos().y ) ) )
305  connected_count++;
306  }
307  else if( item->Parent()->HitTest( wxPoint( Pos().x, Pos().y ) ) )
308  connected_count++;
309  }
310 
311  return connected_count;
312 }
313 
314 
316 {
317  m_items.reserve( 64 );
318  m_originPad = nullptr;
319  m_originNet = -1;
320  m_conflicting = false;
321 }
322 
323 
325 {
326 }
327 
328 
330 {
331  if( !m_originPad || !m_originPad->Valid() )
332  return "<none>";
333  else
334  return m_originPad->Parent()->GetNetname();
335 }
336 
337 
338 bool CN_CLUSTER::Contains( const CN_ITEM* aItem )
339 {
340  return std::find( m_items.begin(), m_items.end(), aItem ) != m_items.end();
341 }
342 
343 
345 {
346  return std::find_if( m_items.begin(), m_items.end(), [ &aItem ] ( const CN_ITEM* item )
347  { return item->Valid() && item->Parent() == aItem; } ) != m_items.end();
348 }
349 
350 
352 {
353  for( auto item : m_items )
354  {
355  wxLogTrace( "CN", " - item : %p bitem : %p type : %d inet %s\n", item, item->Parent(),
356  item->Parent()->Type(), (const char*) item->Parent()->GetNetname().c_str() );
357  printf( "- item : %p bitem : %p type : %d inet %s\n", item, item->Parent(),
358  item->Parent()->Type(), (const char*) item->Parent()->GetNetname().c_str() );
359  item->Dump();
360  }
361 }
362 
363 
365 {
366  m_items.push_back( item );
367 
368  if( item->Net() <= 0 )
369  return;
370 
371  if( m_originNet <= 0 )
372  {
373  m_originNet = item->Net();
374  }
375 
376  if( item->Parent()->Type() == PCB_PAD_T )
377  {
378  if( !m_originPad )
379  {
380  m_originPad = item;
381  m_originNet = item->Net();
382  }
383 
384  if( m_originPad && item->Net() != m_originNet )
385  {
386  m_conflicting = true;
387  }
388  }
389 }
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
const CONNECTED_ITEMS & ConnectedItems() const
bool Contains(const CN_ITEM *aItem)
virtual int AnchorCount() const override
std::vector< CN_ITEM * > m_items
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:57
int GetNetCode() const
Function GetNetCode.
BOARD_CONNECTED_ITEM * m_parent
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
std::shared_ptr< CN_CLUSTER > m_cluster
Cluster to which the anchor belongs.
const wxPoint & GetStart() const
Definition: class_track.h:109
void addItemtoTree(CN_ITEM *item)
bool m_valid
valid flag, used to identify garbage items (we use lazy removal)
CN_ITEM * Add(D_PAD *pad)
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:100
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:178
bool HitTestFilledArea(const wxPoint &aRefPos) const
Function HitTestFilledArea tests if the given wxPoint is within the bounds of a filled area of this z...
Definition: class_zone.cpp:643
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
BOARD_CONNECTED_ITEM * Parent() const
bool IsDangling() const
has meaning only for tracks and vias.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
void SetDirty(bool aDirty=true)
int ConnectedItemsCount() const
has meaning only for tracks and vias.
int Net() const
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:429
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
virtual int AnchorCount() const
std::vector< CN_ITEM * > m_items
Class LSET is a set of PCB_LAYER_IDs.
bool IsOnCopperLayer() const override
Definition: class_pad.h:269
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:426
void Add(CN_ITEM *item)
const wxString & GetNetname() const
Function GetNetname.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
bool Valid() const
virtual const VECTOR2I GetAnchor(int n) const
wxString OriginNetName() const
void AddAnchor(const VECTOR2I &aPos)
virtual const VECTOR2I GetAnchor(int n) const override
CN_ITEM * m_item
Item owning the anchor.
void SetLayer(int aLayer)
Function SetLayer()
CN_ITEM * m_originPad
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
size_t i
Definition: json11.cpp:597
wxPoint ShapePos() const
Definition: class_pad.cpp:570
BOARD_CONNECTED_ITEM * Parent() const
const wxPoint & GetEnd() const
Definition: class_track.h:106
void Remove(T aItem)
Function Remove() Removes an item from the tree.
const VECTOR2I & Pos() const
CONNECTED_ITEMS m_connected
list of items physically connected (touching)
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
Class LAYER_RANGE.
Definition: pns_layerset.h:32
void RemoveInvalidRefs()
bool Valid() const
CN_RTREE< CN_ITEM * > m_index
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:543