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-2007 KiCad Developers, see change_log.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 
39 // see collectors.h
41  // there are some restrictions on the order of items in the general case.
42  // all items in m_Drawings for instance should be contiguous.
43  // *** all items in a same list (shown here) must be contiguous ****
44  PCB_MARKER_T, // in m_markers
45  PCB_TEXT_T, // in m_Drawings
46  PCB_LINE_T, // in m_Drawings
47  PCB_DIMENSION_T, // in m_Drawings
48  PCB_TARGET_T, // in m_Drawings
49  PCB_VIA_T, // in m_Tracks
50  PCB_TRACE_T, // in m_Tracks
51  PCB_PAD_T, // in modules
52  PCB_MODULE_TEXT_T, // in modules
53  PCB_MODULE_T, // in m_Modules
54  PCB_ZONE_T, // in m_Zones
55  PCB_ZONE_AREA_T, // in m_ZoneDescriptorList
56  EOT
57 };
58 
59 
60 /*
61  * const KICAD_T GENERAL_COLLECTOR::PrimaryItems[] = {
62  * PCB_TEXT_T,
63  * PCB_LINE_T,
64  * PCB_DIMENSION_T,
65  * PCB_VIA_T,
66  * PCB_TRACE_T,
67  * PCB_MODULE_T,
68  * EOT
69  * };
70  */
71 
72 
75  PCB_TEXT_T,
76  PCB_LINE_T,
79  PCB_VIA_T,
81  PCB_PAD_T,
84  PCB_ZONE_AREA_T, // if it is visible on screen, it should be selectable
85  EOT
86 };
87 
88 
91  EOT
92 };
93 
94 
96  PCB_PAD_T,
98  EOT
99 };
100 
101 
103  PCB_PAD_T,
104  PCB_VIA_T,
105  PCB_TRACE_T,
106  PCB_ZONE_T,
108  EOT
109 };
110 
111 
115  PCB_PAD_T,
116  PCB_MODULE_T,
117  EOT
118 };
119 
120 
124  PCB_PAD_T,
125  EOT
126 };
127 
128 
130  PCB_TRACE_T,
131  PCB_VIA_T,
132  EOT
133 };
134 
135 
138  EOT
139 };
140 
141 
142 
156 {
157  BOARD_ITEM* item = (BOARD_ITEM*) testItem;
158  MODULE* module = NULL;
159  D_PAD* pad = NULL;
160  bool pad_through = false;
161  VIA* via = NULL;
162  MARKER_PCB* marker = NULL;
163 
164 #if 0 // debugging
165  static int breakhere = 0;
166 
167  switch( item->Type() )
168  {
169  case PCB_PAD_T:
170  {
171  MODULE* m = (MODULE*) item->GetParent();
172 
173  if( m->GetReference() == wxT( "Y2" ) )
174  {
175  breakhere++;
176  }
177  }
178  break;
179 
180  case PCB_VIA_T:
181  breakhere++;
182  break;
183 
184  case PCB_TRACE_T:
185  breakhere++;
186  break;
187 
188  case PCB_ZONE_T:
189  breakhere++;
190  break;
191 
192  case PCB_TEXT_T:
193  breakhere++;
194  break;
195 
196  case PCB_LINE_T:
197  breakhere++;
198  break;
199 
200  case PCB_DIMENSION_T:
201  breakhere++;
202  break;
203 
204  case PCB_MODULE_TEXT_T:
205  {
206  TEXTE_MODULE* tm = (TEXTE_MODULE*) item;
207 
208  if( tm->GetText() == wxT( "10uH" ) )
209  {
210  breakhere++;
211  }
212  }
213  break;
214 
215  case PCB_MODULE_T:
216  {
217  MODULE* m = (MODULE*) item;
218 
219  if( m->GetReference() == wxT( "C98" ) )
220  {
221  breakhere++;
222  }
223  }
224  break;
225 
226  case PCB_MARKER_T:
227  breakhere++;
228  break;
229 
230  default:
231  breakhere++;
232  break;
233  }
234 
235 #endif
236 
237 
238  switch( item->Type() )
239  {
240  case PCB_PAD_T:
241  // there are pad specific visibility controls.
242  // Criterias to select a pad is:
243  // for smd pads: the module parent must be seen, and pads on the corresponding
244  // board side must be seen
245  // if pad is a thru hole, then it can be visible when its parent module is not.
246  // for through pads: pads on Front or Back board sides must be seen
247  pad = (D_PAD*) item;
248 
249  if( (pad->GetAttribute() != PAD_ATTRIB_SMD) &&
250  (pad->GetAttribute() != PAD_ATTRIB_CONN) ) // a hole is present, so multiple layers
251  {
252  // proceed to the common tests below, but without the parent module test,
253  // by leaving module==NULL, but having pad != null
254  pad_through = true;
255  }
256  else // smd, so use pads test after module test
257  {
258  module = static_cast<MODULE*>( item->GetParent() );
259  }
260 
261  break;
262 
263  case PCB_VIA_T: // vias are on many layers, so layer test is specific
264  via = static_cast<VIA*>( item );
265  break;
266 
267  case PCB_TRACE_T:
268  break;
269 
270  case PCB_ZONE_T:
271  break;
272 
273  case PCB_ZONE_AREA_T:
274  break;
275 
276  case PCB_TEXT_T:
277  break;
278 
279  case PCB_LINE_T:
280  break;
281 
282  case PCB_DIMENSION_T:
283  break;
284 
285  case PCB_TARGET_T:
286  break;
287 
288  case PCB_MODULE_TEXT_T:
289  {
290  TEXTE_MODULE *text = static_cast<TEXTE_MODULE*>( item );
291  if( m_Guide->IgnoreMTextsMarkedNoShow() && !text->IsVisible() )
292  goto exit;
293 
294  if( m_Guide->IgnoreMTextsOnBack() && IsBackLayer( text->GetLayer() ) )
295  goto exit;
296 
297  if( m_Guide->IgnoreMTextsOnFront() && IsFrontLayer( text->GetLayer() ) )
298  goto exit;
299 
300  /* The three text types have different criteria: reference
301  * and value have their own ignore flags; user text instead
302  * follows their layer visibility. Checking this here is
303  * simpler than later (when layer visibility is checked for
304  * other entities) */
305 
306  switch( text->GetType() )
307  {
309  if( m_Guide->IgnoreModulesRefs() )
310  goto exit;
311  break;
312 
314  if( m_Guide->IgnoreModulesVals() )
315  goto exit;
316  break;
317 
319  if( !m_Guide->IsLayerVisible( text->GetLayer() )
321  goto exit;
322  break;
323  }
324 
325  // Extract the module since it could be hidden
326  module = static_cast<MODULE*>( item->GetParent() );
327  }
328  break;
329 
330  case PCB_MODULE_T:
331  module = static_cast<MODULE*>( item );
332  break;
333 
334  case PCB_MARKER_T:
335  marker = static_cast<MARKER_PCB*>( item );
336  break;
337 
338  default:
339  break;
340  }
341 
342  // common tests:
343 
344  if( module ) // true from case PCB_PAD_T, PCB_MODULE_TEXT_T, or PCB_MODULE_T
345  {
346  if( m_Guide->IgnoreModulesOnBack() && (module->GetLayer() == B_Cu) )
347  goto exit;
348 
349  if( m_Guide->IgnoreModulesOnFront() && (module->GetLayer() == F_Cu) )
350  goto exit;
351  }
352 
353  // Pads are not sensitive to the layer visibility controls.
354  // They all have their own separate visibility controls
355  // skip them if not visible
356  if( pad )
357  {
358  if( m_Guide->IgnorePads() )
359  goto exit;
360 
361  if( ! pad_through )
362  {
363  if( m_Guide->IgnorePadsOnFront() && pad->IsOnLayer(F_Cu ) )
364  goto exit;
365 
366  if( m_Guide->IgnorePadsOnBack() && pad->IsOnLayer(B_Cu ) )
367  goto exit;
368  }
369  }
370 
371  if( marker )
372  {
373  // Markers are not sensitive to the layer
374  if( marker->HitTest( m_RefPos ) )
375  Append( item );
376 
377  goto exit;
378  }
379 
380  if( item->IsOnLayer( m_Guide->GetPreferredLayer() ) ||
382  {
383  PCB_LAYER_ID layer = item->GetLayer();
384 
385  /* Modules and their subcomponents: reference, value and pads
386  * are not sensitive to the layer visibility controls. They all
387  * have their own separate visibility controls for vias,
388  * GetLayer() has no meaning, but IsOnLayer() works fine. User
389  * text in module *is* sensitive to layer visibility but that
390  * was already handled */
391 
392  if( via || module || pad || m_Guide->IsLayerVisible( layer )
394  {
395  if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
396  {
397  if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
398  {
399  if( item->HitTest( m_RefPos ) )
400  {
401  Append( item );
402  goto exit;
403  }
404  }
405  }
406  }
407  }
408 
409 
410  if( m_Guide->IncludeSecondary() )
411  {
412  // for now, "secondary" means "tolerate any layer". It has
413  // no effect on other criteria, since there is a separate "ignore" control for
414  // those in the COLLECTORS_GUIDE
415 
416  PCB_LAYER_ID layer = item->GetLayer();
417 
418  /* Modules and their subcomponents: reference, value and pads
419  * are not sensitive to the layer visibility controls. They all
420  * have their own separate visibility controls. User texts
421  * follows layer visibility controls (but that was already
422  * checked) */
423 
424  if( via || module || pad || m_Guide->IsLayerVisible( layer )
426  {
427  if( !m_Guide->IsLayerLocked( layer ) || !m_Guide->IgnoreLockedLayers() )
428  {
429  if( !item->IsLocked() || !m_Guide->IgnoreLockedItems() )
430  {
431  if( item->HitTest( m_RefPos ) )
432  {
433  Append2nd( item );
434  goto exit;
435  }
436  }
437  }
438  }
439  }
440 
441 exit:
442  return SEARCH_CONTINUE; // always when collecting
443 }
444 
445 
446 // see collectors.h
447 void GENERAL_COLLECTOR::Collect( BOARD_ITEM* aItem, const KICAD_T aScanList[],
448  const wxPoint& aRefPos, const COLLECTORS_GUIDE& aGuide )
449 {
450  Empty(); // empty the collection, primary criteria list
451  Empty2nd(); // empty the collection, secondary criteria list
452 
453  // remember guide, pass it to Inspect()
454  SetGuide( &aGuide );
455 
456  SetScanTypes( aScanList );
457 
458  // remember where the snapshot was taken from and pass refPos to
459  // the Inspect() function.
460  SetRefPos( aRefPos );
461 
462  aItem->Visit( m_inspector, NULL, m_ScanTypes );
463 
464  SetTimeNow(); // when snapshot was taken
465 
466  // record the length of the primary list before concatenating on to it.
467  m_PrimaryLength = m_List.size();
468 
469  // append 2nd list onto end of the first list
470  for( unsigned i = 0; i<m_List2nd.size(); ++i )
471  Append( m_List2nd[i] );
472 
473  Empty2nd();
474 }
475 
476 
477 // see collectors.h
479 {
480  // The Vist() function only visits the testItem if its type was in the
481  // the scanList, so therefore we can collect anything given to us here.
482  Append( testItem );
483 
484  return SEARCH_CONTINUE; // always when collecting
485 }
486 
487 
488 void PCB_TYPE_COLLECTOR::Collect( BOARD_ITEM* aBoard, const KICAD_T aScanList[] )
489 {
490  Empty(); // empty any existing collection
491 
492  aBoard->Visit( m_inspector, NULL, aScanList );
493 }
void Empty()
Function Empty sets the list to empty.
virtual bool IsLayerLocked(PCB_LAYER_ID layer) const =0
Function IsLayerLocked.
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...
virtual bool IgnoreModulesOnFront() const =0
Function IgnoreModulesOnFront.
static const KICAD_T PadsTracksOrZones[]
A scan list for PADs, TRACKs, VIAs, or ZONEs.
Definition: collectors.h:276
static const KICAD_T AllBoardItems[]
A scan list for all editable board items, like PcbGeneralLocateAndDisplay()
Definition: collectors.h:241
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:238
static const KICAD_T Tracks[]
A scan list for only TRACKS.
Definition: collectors.h:294
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 all primary board items, omitting items which are subordinate to a MODULE...
Definition: collectors.h:265
TEXT_TYPE GetType() const
void SetScanTypes(const KICAD_T *scanTypes)
Function SetScanTypes records the list of KICAD_T types to consider for collection by the Inspect() f...
void Collect(BOARD_ITEM *aItem, const KICAD_T aScanList[], const wxPoint &aRefPos, const COLLECTORS_GUIDE &aGuide)
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection...
Definition: collectors.cpp:447
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
virtual bool IgnoreNonVisibleLayers() const =0
Function IgnoredNonVisibleLayers.
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:59
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:114
void Append2nd(BOARD_ITEM *item)
Definition: collectors.h:312
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:104
virtual PCB_LAYER_ID GetPreferredLayer() const =0
Function GetPreferredLayer.
static const KICAD_T AllButZones[]
A scan list for all editable board items, except zones.
Definition: collectors.h:247
std::vector< BOARD_ITEM * > m_List2nd
A place to hold collected objects which don't match precisely the search criteria, but would be acceptable if nothing else is found.
Definition: collectors.h:220
class D_PAD, a pad in a footprint
Definition: typeinfo.h:102
virtual bool IgnoreModulesVals() const =0
Function IgnoreModulesVals.
virtual bool IgnorePads() const
Function IgnorePads.
Definition: collectors.h:173
int m_PrimaryLength
The number of items that were originally in the primary list before the m_List2nd was concatenated on...
Definition: collectors.h:233
virtual bool IgnorePreferredLayer() const =0
Function IgnorePreferredLayer provides wildcard behavior regarding the preferred layer.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:106
search types array terminator (End Of Types)
Definition: typeinfo.h:94
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
Functions relatives to tracks, vias and segments used to fill zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
static const KICAD_T ModulesAndTheirItems[]
A scan list for MODULEs and their items (for Modedit)
Definition: collectors.h:282
virtual bool IgnorePadsOnFront() const =0
Function IgnorePadsOnFront.
void Append(EDA_ITEM *item)
Function Append adds an item to the end of the list.
void SetGuide(const COLLECTORS_GUIDE *aGuide)
Function SetGuide records which COLLECTORS_GUIDE to use.
Definition: collectors.h:323
class MODULE, a footprint
Definition: typeinfo.h:101
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
Function Inspect is the examining function within the INSPECTOR which is passed to the Iterate functi...
Definition: collectors.cpp:478
Markers used to show a drc problem on boards.
INSPECTOR_FUNC m_inspector
a class common bridge into the polymorphic Inspect()
PCB_LAYER_ID
A quick note on layer IDs:
virtual bool IgnoreMTextsOnBack() const =0
Function IgnoreZones.
void SetRefPos(const wxPoint &aRefPos)
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
static const KICAD_T Zones[]
A scan list for zones outlines only.
Definition: collectors.h:252
class SEGZONE, a segment used to fill a zone area (segment on a copper layer)
Definition: typeinfo.h:109
const COLLECTORS_GUIDE * m_Guide
Determines which items are to be collected by Inspect()
Definition: collectors.h:226
virtual bool IgnoreMTextsMarkedNoShow() const =0
Function IgnoreMTextsMarkedNoShow.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:60
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
void Collect(BOARD_ITEM *aBoard, const KICAD_T aScanList[])
Function Collect scans a BOARD_ITEM using this class's Inspector method, which does the collection...
Definition: collectors.cpp:488
Pad object description.
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:113
virtual bool IgnoreModulesRefs() const =0
Function IgnoreModulesRefs.
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:105
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it'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...
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:111
void SetTimeNow()
static const KICAD_T PadsOrModules[]
A scan list for PADs or MODULEs.
Definition: collectors.h:271
const wxString & GetReference() const
Function GetReference.
Definition: class_module.h:419
virtual bool IsLocked() const
Function IsLocked.
bool IsVisible() const
Definition: eda_text.h:176
static const KICAD_T ModuleItems[]
A scan list for primary module items.
Definition: collectors.h:288
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
Function IsLayerVisible.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
virtual bool IgnorePadsOnBack() const =0
Function IgnorePadsOnBack.
wxPoint m_RefPos
A point to test against, and that was used to make the collection.
Module description (excepted pads)
Class COLLECTORS_GUIDE is an abstract base class whose derivatives may be passed to a GENERAL_COLLECT...
Definition: collectors.h:64
virtual bool IgnoreLockedItems() const =0
Function IgnoreLockedItems.
virtual bool IgnoreLockedLayers() const =0
Function IgnoreLockedLayers.
SEARCH_RESULT
Definition: base_struct.h:68
std::vector< EDA_ITEM * > m_List
A place to hold collected objects without taking ownership of their memory.
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:479
virtual bool IgnoreModulesOnBack() const =0
Function IgnoreModulesOnBack.
virtual bool IgnoreMTextsOnFront() const =0
Function IgnoreMTextsOnFront.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
virtual bool IncludeSecondary() const =0
Function IncludeSecondary determines if the secondary criteria, or 2nd choice items should be include...
const KICAD_T * m_ScanTypes
Which object types to scan.
SEARCH_RESULT Inspect(EDA_ITEM *testItem, void *testData) override
Function Inspect is the examining function within the INSPECTOR which is passed to the Iterate functi...
Definition: collectors.cpp:155