KiCad PCB EDA Suite
collectors.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) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
5  * Copyright (C) 2004-2018 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <collectors.h>
26 #include <class_board_item.h> // class BOARD_ITEM
27 
28 #include <class_module.h>
29 #include <class_pad.h>
30 #include <class_track.h>
31 #include <class_marker_pcb.h>
32 
33 
34 /* This module contains out of line member functions for classes given in
35  * collectors.h. Those classes augment the functionality of class PCB_EDIT_FRAME.
36  */
37 
38 
40  // there are some restrictions on the order of items in the general case.
41  // all items in m_Drawings for instance should be contiguous.
42  // *** all items in a same list (shown here) must be contiguous ****
43  PCB_MARKER_T, // in m_markers
44  PCB_TEXT_T, // in m_Drawings
45  PCB_LINE_T, // in m_Drawings
46  PCB_DIMENSION_T, // in m_Drawings
47  PCB_TARGET_T, // in m_Drawings
48  PCB_VIA_T, // in m_Tracks
49  PCB_TRACE_T, // in m_Tracks
50  PCB_PAD_T, // in modules
51  PCB_MODULE_TEXT_T, // in modules
52  PCB_MODULE_T, // in m_Modules
53  PCB_ZONE_T, // in m_Zones
54  PCB_ZONE_AREA_T, // in m_ZoneDescriptorList
55  EOT
56 };
57 
58 
61  PCB_TEXT_T,
62  PCB_LINE_T,
65  PCB_VIA_T,
68  PCB_ZONE_T,
70  EOT
71 };
72 
73 
76  PCB_TEXT_T,
77  PCB_LINE_T,
80  PCB_VIA_T,
82  PCB_PAD_T,
85  PCB_ZONE_AREA_T, // if it is visible on screen, it should be selectable
86  EOT
87 };
88 
89 
92  EOT
93 };
94 
95 
97  PCB_PAD_T,
99  EOT
100 };
101 
102 
104  PCB_PAD_T,
105  PCB_VIA_T,
106  PCB_TRACE_T,
107  PCB_ZONE_T,
109  EOT
110 };
111 
112 
116  PCB_PAD_T,
117  PCB_MODULE_T,
118  EOT
119 };
120 
121 
125  PCB_PAD_T,
126  EOT
127 };
128 
129 
131  PCB_TRACE_T,
132  PCB_VIA_T,
133  EOT
134 };
135 
136 
138  PCB_MODULE_T,
139  PCB_TRACE_T,
140  PCB_VIA_T,
141  EOT
142 };
143 
144 
147  EOT
148 };
149 
150 
151 
153 {
154  BOARD_ITEM* item = (BOARD_ITEM*) testItem;
155  MODULE* module = NULL;
156  D_PAD* pad = NULL;
157  bool pad_through = false;
158  VIA* via = NULL;
159  MARKER_PCB* marker = NULL;
160 
161 #if 0 // debugging
162  static int breakhere = 0;
163 
164  switch( item->Type() )
165  {
166  case PCB_PAD_T:
167  {
168  MODULE* m = (MODULE*) item->GetParent();
169 
170  if( m->GetReference() == wxT( "Y2" ) )
171  {
172  breakhere++;
173  }
174  }
175  break;
176 
177  case PCB_VIA_T:
178  breakhere++;
179  break;
180 
181  case PCB_TRACE_T:
182  breakhere++;
183  break;
184 
185  case PCB_ZONE_T:
186  breakhere++;
187  break;
188 
189  case PCB_TEXT_T:
190  breakhere++;
191  break;
192 
193  case PCB_LINE_T:
194  breakhere++;
195  break;
196 
197  case PCB_DIMENSION_T:
198  breakhere++;
199  break;
200 
201  case PCB_MODULE_TEXT_T:
202  {
203  TEXTE_MODULE* tm = (TEXTE_MODULE*) item;
204 
205  if( tm->GetText() == wxT( "10uH" ) )
206  {
207  breakhere++;
208  }
209  }
210  break;
211 
212  case PCB_MODULE_T:
213  {
214  MODULE* m = (MODULE*) item;
215 
216  if( m->GetReference() == wxT( "C98" ) )
217  {
218  breakhere++;
219  }
220  }
221  break;
222 
223  case PCB_MARKER_T:
224  breakhere++;
225  break;
226 
227  default:
228  breakhere++;
229  break;
230  }
231 
232 #endif
233 
234 
235  switch( item->Type() )
236  {
237  case PCB_PAD_T:
238  // there are pad specific visibility controls.
239  // Criterias to select a pad is:
240  // for smd pads: the module parent must be seen, and pads on the corresponding
241  // board side must be seen
242  // if pad is a thru hole, then it can be visible when its parent module is not.
243  // for through pads: pads on Front or Back board sides must be seen
244  pad = (D_PAD*) item;
245 
246  if( (pad->GetAttribute() != PAD_ATTRIB_SMD) &&
247  (pad->GetAttribute() != PAD_ATTRIB_CONN) ) // a hole is present, so multiple layers
248  {
249  // proceed to the common tests below, but without the parent module test,
250  // by leaving module==NULL, but having pad != null
251  pad_through = true;
252  }
253  else // smd, so use pads test after module test
254  {
255  module = static_cast<MODULE*>( item->GetParent() );
256  }
257 
258  break;
259 
260  case PCB_VIA_T: // vias are on many layers, so layer test is specific
261  via = static_cast<VIA*>( item );
262  break;
263 
264  case PCB_TRACE_T:
265  if( m_Guide->IgnoreTracks() )
266  goto exit;
267  break;
268 
269  case PCB_ZONE_T:
270  break;
271 
272  case PCB_ZONE_AREA_T:
273  break;
274 
275  case PCB_TEXT_T:
276  break;
277 
278  case PCB_LINE_T:
279  break;
280 
281  case PCB_DIMENSION_T:
282  break;
283 
284  case PCB_TARGET_T:
285  break;
286 
287  case PCB_MODULE_TEXT_T:
288  {
289  TEXTE_MODULE *text = static_cast<TEXTE_MODULE*>( item );
290  if( m_Guide->IgnoreMTextsMarkedNoShow() && !text->IsVisible() )
291  goto exit;
292 
293  if( m_Guide->IgnoreMTextsOnBack() && IsBackLayer( text->GetLayer() ) )
294  goto exit;
295 
296  if( m_Guide->IgnoreMTextsOnFront() && IsFrontLayer( text->GetLayer() ) )
297  goto exit;
298 
299  /* The three text types have different criteria: reference
300  * and value have their own ignore flags; user text instead
301  * follows their layer visibility. Checking this here is
302  * simpler than later (when layer visibility is checked for
303  * other entities) */
304 
305  switch( text->GetType() )
306  {
308  if( m_Guide->IgnoreModulesRefs() )
309  goto exit;
310  break;
311 
313  if( m_Guide->IgnoreModulesVals() )
314  goto exit;
315  break;
316 
318  if( !m_Guide->IsLayerVisible( text->GetLayer() )
320  goto exit;
321  break;
322  }
323 
324  // Extract the module since it could be hidden
325  module = static_cast<MODULE*>( item->GetParent() );
326  }
327  break;
328 
329  case PCB_MODULE_T:
330  module = static_cast<MODULE*>( item );
331  break;
332 
333  case PCB_MARKER_T:
334  marker = static_cast<MARKER_PCB*>( item );
335  break;
336 
337  default:
338  break;
339  }
340 
341  // common tests:
342 
343  if( module ) // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T
344  {
345  if( m_Guide->IgnoreModulesOnBack() && (module->GetLayer() == B_Cu) )
346  goto exit;
347 
348  if( m_Guide->IgnoreModulesOnFront() && (module->GetLayer() == F_Cu) )
349  goto exit;
350  }
351 
352  // Pads are not sensitive to the layer visibility controls.
353  // They all have their own separate visibility controls
354  // skip them if not visible
355  if( pad )
356  {
357  if( m_Guide->IgnorePads() )
358  goto exit;
359 
360  if( ! pad_through )
361  {
362  if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(F_Cu ) )
363  goto exit;
364 
365  if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(B_Cu ) )
366  goto exit;
367  }
368  }
369 
370  if( marker )
371  {
372  // Markers are not sensitive to the layer
373  if( marker->HitTest( m_RefPos ) )
374  Append( item );
375 
376  goto exit;
377  }
378 
379  if( via )
380  {
381  auto type = via->GetViaType();
382 
383  if( ( m_Guide->IgnoreThroughVias() && type == VIA_THROUGH ) ||
384  ( m_Guide->IgnoreBlindBuriedVias() && type == VIA_BLIND_BURIED ) ||
385  ( m_Guide->IgnoreMicroVias() && type == VIA_MICROVIA ) )
386  {
387  goto exit;
388  }
389  }
390 
391  if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) ||
393  {
394  PCB_LAYER_ID layer = item->GetLayer();
395 
396  /* Modules and their subcomponents: reference, value and pads
397  * are not sensitive to the layer visibility controls. They all
398  * have their own separate visibility controls for vias,
399  * GetLayer() has no meaning, but IsOnLayer() works fine. User
400  * text in module *is* sensitive to layer visibility but that
401  * was already handled */
402 
403  if( via || module || pad || m_Guide->IsLayerVisible( layer )
405  {
406  if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
407  {
408  if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
409  {
410  if( item->HitTest( m_RefPos ) )
411  {
412  if( !module || module->HitTestAccurate( m_RefPos ) )
413  Append( item );
414  goto exit;
415  }
416  }
417  }
418  }
419  }
420 
421 
422  if( m_Guide->IncludeSecondary() )
423  {
424  // for now, "secondary" means "tolerate any layer". It has
425  // no effect on other criteria, since there is a separate "ignore" control for
426  // those in the COLLECTORS_GUIDE
427 
428  PCB_LAYER_ID layer = item->GetLayer();
429 
430  /* Modules and their subcomponents: reference, value and pads
431  * are not sensitive to the layer visibility controls. They all
432  * have their own separate visibility controls. User texts
433  * follows layer visibility controls (but that was already
434  * checked) */
435 
436  if( via || module || pad || m_Guide->IsLayerVisible( layer )
438  {
439  if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
440  {
441  if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
442  {
443  if( item->HitTest( m_RefPos ) )
444  {
445  Append2nd( item );
446  goto exit;
447  }
448  }
449  }
450  }
451  }
452 
453 exit:
454  return SEARCH_CONTINUE; // always when collecting
455 }
456 
457 
458 void GENERAL_COLLECTOR::Collect( BOARD_ITEM* aItem, const KICAD_T aScanList[],
459  const wxPoint& aRefPos, const COLLECTORS_GUIDE& aGuide )
460 {
461  Empty(); // empty the collection, primary criteria list
462  Empty2nd(); // empty the collection, secondary criteria list
463 
464  // remember guide, pass it to Inspect()
465  SetGuide( &aGuide );
466 
467  SetScanTypes( aScanList );
468 
469  // remember where the snapshot was taken from and pass refPos to
470  // the Inspect() function.
471  SetRefPos( aRefPos );
472 
473  aItem->Visit( m_inspector, NULL, m_ScanTypes );
474 
475  SetTimeNow(); // when snapshot was taken
476 
477  // record the length of the primary list before concatenating on to it.
478  m_PrimaryLength = m_List.size();
479 
480  // append 2nd list onto end of the first list
481  for( unsigned i = 0; i<m_List2nd.size(); ++i )
482  Append( m_List2nd[i] );
483 
484  Empty2nd();
485 }
486 
487 
489 {
490  // The Visit() function only visits the testItem if its type was in the
491  // the scanList, so therefore we can collect anything given to us here.
492  Append( testItem );
493 
494  return SEARCH_CONTINUE; // always when collecting
495 }
496 
497 
498 void PCB_TYPE_COLLECTOR::Collect( BOARD_ITEM* aBoard, const KICAD_T aScanList[] )
499 {
500  Empty(); // empty any existing collection
501 
502  aBoard->Visit( m_inspector, NULL, aScanList );
503 }
504 
505 
507 {
508  BOARD_ITEM* item = (BOARD_ITEM*) testItem;
509 
510  if( item->Type() == PCB_PAD_T ) // multilayer
511  {
512  if( static_cast<D_PAD*>( item )->IsOnLayer( m_layer_id ) )
513  Append( testItem );
514  }
515  else if( item->GetLayer() == m_layer_id )
516  Append( testItem );
517 
518  return SEARCH_CONTINUE;
519 }
520 
521 
522 void PCB_LAYER_COLLECTOR::Collect( BOARD_ITEM* aBoard, const KICAD_T aScanList[] )
523 {
524  Empty();
525 
526  aBoard->Visit( m_inspector, NULL, aScanList );
527 }
void Empty()
Function Empty sets the list to empty.
Definition: collector.h:115
virtual bool IsLayerLocked(PCB_LAYER_ID layer) const =0
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
BOARD_ITEM_CONTAINER * GetParent() const
virtual SEARCH_RESULT Visit(INSPECTOR inspector, void *testData, const KICAD_T scanTypes[])
Function Visit may be re-implemented for each derived class in order to handle all the types given by...
static const KICAD_T BoardLevelItems[]
A scan list for all primary board items, omitting items which are subordinate to a MODULE...
Definition: collectors.h:275
virtual bool IgnoreBlindBuriedVias() const =0
virtual bool IgnoreModulesOnFront() const =0
static const KICAD_T PadsTracksOrZones[]
A scan list for PADs, TRACKs, VIAs, or ZONEs.
Definition: collectors.h:290
static const KICAD_T AllBoardItems[]
A scan list for all editable board items, like PcbGeneralLocateAndDisplay()
Definition: collectors.h:259
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:405
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:305
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
The examining function within the INSPECTOR which is passed to the iterate function.
Definition: collectors.cpp:506
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
static const KICAD_T Modules[]
A scan list for only MODULEs.
Definition: collectors.h:280
TEXT_TYPE GetType() const
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
void SetScanTypes(const KICAD_T *scanTypes)
Function SetScanTypes records the list of KICAD_T types to consider for collection by the Inspect() f...
Definition: collector.h:207
void Collect(BOARD_ITEM *aItem, const KICAD_T aScanList[], const wxPoint &aRefPos, const COLLECTORS_GUIDE &aGuide)
Scan a BOARD_ITEM using this class&#39;s Inspector method, which does the collection. ...
Definition: collectors.cpp:458
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it&#39;s a back layer.
virtual bool IgnoreNonVisibleLayers() const =0
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:61
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
void Append2nd(BOARD_ITEM *item)
Definition: collectors.h:327
bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
virtual PCB_LAYER_ID GetPreferredLayer() const =0
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Tests a BOARD_ITEM using this class&#39;s Inspector method, which does the collection.
Definition: collectors.cpp:522
static const KICAD_T AllButZones[]
A scan list for all editable board items, except zones.
Definition: collectors.h:264
virtual bool IgnoreTracks() const =0
std::vector< BOARD_ITEM * > m_List2nd
A place to hold collected objects which don&#39;t match precisely the search criteria, but would be acceptable if nothing else is found.
Definition: collectors.h:241
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
virtual bool IgnoreMicroVias() const =0
virtual bool IgnoreModulesVals() const =0
virtual bool IgnorePads() const
Definition: collectors.h:151
int m_PrimaryLength
The number of items that were originally in the primary list before the m_List2nd was concatenated on...
Definition: collectors.h:252
virtual bool IgnorePreferredLayer() const =0
Provide wildcard behavior regarding the preferred layer.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
static const KICAD_T ModulesAndTheirItems[]
A scan list for MODULEs and their items (for Modedit)
Definition: collectors.h:295
virtual bool IgnorePadsOnFront() const =0
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
Definition: collector.h:125
void SetGuide(const COLLECTORS_GUIDE *aGuide)
Record which COLLECTORS_GUIDE to use.
Definition: collectors.h:337
class MODULE, a footprint
Definition: typeinfo.h:89
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
The examining function within the INSPECTOR which is passed to the Iterate function.
Definition: collectors.cpp:488
Markers used to show a drc problem on boards.
INSPECTOR_FUNC m_inspector
a class common bridge into the polymorphic Inspect()
Definition: collector.h:59
PCB_LAYER_ID
A quick note on layer IDs:
VIATYPE_T GetViaType() const
Definition: class_track.h:454
virtual bool IgnoreMTextsOnBack() const =0
void SetRefPos(const wxPoint &aRefPos)
Definition: collector.h:222
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
static const KICAD_T Zones[]
A scan list for zones outlines only.
Definition: collectors.h:269
class SEGZONE, a segment used to fill a zone area (segment on a copper layer)
Definition: typeinfo.h:97
const COLLECTORS_GUIDE * m_Guide
Determines which items are to be collected by Inspect()
Definition: collectors.h:246
virtual bool IgnoreMTextsMarkedNoShow() const =0
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:62
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:100
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Collect BOARD_ITEM objects using this class&#39;s Inspector method, which does the collection.
Definition: collectors.cpp:498
virtual bool IgnoreThroughVias() const =0
Pad object description.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:101
virtual bool IgnoreModulesRefs() const =0
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it&#39;s a front layer.
virtual bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
static const KICAD_T LockableItems[]
A scan list for TRACKS, VIAS, MODULES.
Definition: collectors.h:310
bool HitTestAccurate(const wxPoint &aPosition) const
Tests if a point is inside the bounding polygon of the module.
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
void SetTimeNow()
Definition: collector.h:212
static const KICAD_T PadsOrModules[]
A scan list for PADs or MODULEs.
Definition: collectors.h:285
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:460
virtual bool IsLocked() const
Function IsLocked.
bool IsVisible() const
Definition: eda_text.h:189
static const KICAD_T ModuleItems[]
A scan list for primary module items.
Definition: collectors.h:300
size_t i
Definition: json11.cpp:597
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:151
virtual bool IsLayerVisible(PCB_LAYER_ID layer) const =0
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
virtual bool IgnorePadsOnBack() const =0
wxPoint m_RefPos
A point to test against, and that was used to make the collection.
Definition: collector.h:68
Module description (excepted pads)
An abstract base class whose derivatives may be passed to a GENERAL_COLLECTOR, telling GENERAL_COLLEC...
Definition: collectors.h:63
virtual bool IgnoreLockedItems() const =0
virtual bool IgnoreLockedLayers() const =0
SEARCH_RESULT
Definition: base_struct.h:66
std::vector< EDA_ITEM * > m_List
A place to hold collected objects without taking ownership of their memory.
Definition: collector.h:65
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:660
virtual bool IgnoreModulesOnBack() const =0
virtual bool IgnoreMTextsOnFront() const =0
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
virtual bool IncludeSecondary() const =0
Determine if the secondary criteria or 2nd choice items should be included.
const KICAD_T * m_ScanTypes
Which object types to scan.
Definition: collector.h:62
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
The examining function within the INSPECTOR which is passed to the Iterate function.
Definition: collectors.cpp:152