KiCad PCB EDA Suite
drc_test_provider.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) 2020 KiCad Developers, see change_log.txt for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <drc/drc_engine.h>
25 #include <drc/drc_item.h>
26 #include <drc/drc_test_provider.h>
27 #include <track.h>
28 #include <footprint.h>
29 #include <pad.h>
30 #include <zone.h>
31 #include <pcb_text.h>
32 
33 
34 // A list of all basic (ie: non-compound) board geometry items
35 std::vector<KICAD_T> DRC_TEST_PROVIDER::s_allBasicItems;
37 
38 
40 {
41  for( DRC_TEST_PROVIDER* provider : m_providers )
42  delete provider;
43 }
44 
45 
47  m_drcEngine( nullptr )
48 {
49 }
50 
51 
52 const wxString DRC_TEST_PROVIDER::GetName() const { return "<no name test>"; }
53 const wxString DRC_TEST_PROVIDER::GetDescription() const { return ""; }
54 
55 
56 void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item, wxPoint aMarkerPos )
57 {
58  if( item->GetViolatingRule() )
59  accountCheck( item->GetViolatingRule() );
60 
61  item->SetViolatingTest( this );
62  m_drcEngine->ReportViolation( item, aMarkerPos );
63 }
64 
65 
66 bool DRC_TEST_PROVIDER::reportProgress( int aCount, int aSize, int aDelta )
67 {
68  if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
69  {
70  if( !m_drcEngine->ReportProgress( (double) aCount / (double) aSize ) )
71  return false;
72  }
73 
74  return true;
75 }
76 
77 
78 bool DRC_TEST_PROVIDER::reportPhase( const wxString& aMessage )
79 {
80  reportAux( aMessage );
81  return m_drcEngine->ReportPhase( aMessage );
82 }
83 
84 
85 void DRC_TEST_PROVIDER::reportAux( wxString fmt, ... )
86 {
87  va_list vargs;
88  va_start( vargs, fmt );
89  wxString str;
90  str.PrintfV( fmt, vargs );
91  va_end( vargs );
92  m_drcEngine->ReportAux( str );
93 }
94 
95 
97 {
98  return m_drcEngine->UserUnits();
99 }
100 
101 
102 void DRC_TEST_PROVIDER::accountCheck( const DRC_RULE* ruleToTest )
103 {
104  auto it = m_stats.find( ruleToTest );
105 
106  if( it == m_stats.end() )
107  m_stats[ ruleToTest ] = 1;
108  else
109  m_stats[ ruleToTest ] += 1;
110 }
111 
112 
113 void DRC_TEST_PROVIDER::accountCheck( const DRC_CONSTRAINT& constraintToTest )
114 {
115  accountCheck( constraintToTest.GetParentRule() );
116 }
117 
118 
120 {
121  if( !m_isRuleDriven )
122  return;
123 
124  m_drcEngine->ReportAux( "Rule hit statistics: " );
125 
126  for( const std::pair<const DRC_RULE* const, int>& stat : m_stats )
127  {
128  if( stat.first )
129  {
130  m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ",
131  stat.first->m_Name,
132  stat.second ) );
133  }
134  }
135 }
136 
137 
138 int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, LSET aLayers,
139  const std::function<bool( BOARD_ITEM*)>& aFunc )
140 {
141  BOARD *brd = m_drcEngine->GetBoard();
142  std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
143  int n = 0;
144 
145  if( s_allBasicItems.size() == 0 )
146  {
147  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
148  {
149  if( i != PCB_FOOTPRINT_T && i != PCB_GROUP_T )
150  {
151  s_allBasicItems.push_back( (KICAD_T) i );
152 
153  if( i != PCB_ZONE_T && i != PCB_FP_ZONE_T )
154  s_allBasicItemsButZones.push_back( (KICAD_T) i );
155  }
156  }
157  }
158 
159  if( aTypes.size() == 0 )
160  {
161  for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
162  typeMask[ i ] = true;
163  }
164  else
165  {
166  for( KICAD_T aType : aTypes )
167  typeMask[ aType ] = true;
168  }
169 
170  for( TRACK* item : brd->Tracks() )
171  {
172  if( (item->GetLayerSet() & aLayers).any() )
173  {
174  if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
175  {
176  aFunc( item );
177  n++;
178  }
179  else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
180  {
181  aFunc( item );
182  n++;
183  }
184  else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
185  {
186  aFunc( item );
187  n++;
188  }
189  }
190  }
191 
192  for( BOARD_ITEM* item : brd->Drawings() )
193  {
194  if( (item->GetLayerSet() & aLayers).any() )
195  {
196  if( typeMask[PCB_DIMENSION_T] && BaseType( item->Type() ) == PCB_DIMENSION_T )
197  {
198  if( !aFunc( item ) )
199  return n;
200 
201  n++;
202  }
203  else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T )
204  {
205  if( !aFunc( item ) )
206  return n;
207 
208  n++;
209  }
210  else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
211  {
212  if( !aFunc( item ) )
213  return n;
214 
215  n++;
216  }
217  else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
218  {
219  if( !aFunc( item ) )
220  return n;
221 
222  n++;
223  }
224  }
225  }
226 
227  if( typeMask[ PCB_ZONE_T ] )
228  {
229  for( ZONE* item : brd->Zones() )
230  {
231  if( ( item->GetLayerSet() & aLayers ).any() )
232  {
233  if( !aFunc( item ) )
234  return n;
235 
236  n++;
237  }
238  }
239  }
240 
241  for( FOOTPRINT* footprint : brd->Footprints() )
242  {
243  if( typeMask[ PCB_FP_TEXT_T ] )
244  {
245  if( ( footprint->Reference().GetLayerSet() & aLayers ).any() )
246  {
247  if( !aFunc( &footprint->Reference() ) )
248  return n;
249 
250  n++;
251  }
252 
253  if( ( footprint->Value().GetLayerSet() & aLayers ).any() )
254  {
255  if( !aFunc( &footprint->Value() ) )
256  return n;
257 
258  n++;
259  }
260  }
261 
262  if( typeMask[ PCB_PAD_T ] )
263  {
264  for( PAD* pad : footprint->Pads() )
265  {
266  // Careful: if a pad has a hole then it pierces all layers
267  if( ( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
268  || ( pad->GetLayerSet() & aLayers ).any() )
269  {
270  if( !aFunc( pad ) )
271  return n;
272 
273  n++;
274  }
275  }
276  }
277 
278  for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
279  {
280  if( (dwg->GetLayerSet() & aLayers).any() )
281  {
282  if( typeMask[ PCB_FP_TEXT_T ] && dwg->Type() == PCB_FP_TEXT_T )
283  {
284  if( !aFunc( dwg ) )
285  return n;
286 
287  n++;
288  }
289  else if( typeMask[ PCB_FP_SHAPE_T ] && dwg->Type() == PCB_FP_SHAPE_T )
290  {
291  if( !aFunc( dwg ) )
292  return n;
293 
294  n++;
295  }
296  }
297  }
298 
299  if( typeMask[ PCB_FP_ZONE_T ] )
300  {
301  for( ZONE* zone : footprint->Zones() )
302  {
303  if( (zone->GetLayerSet() & aLayers).any() )
304  {
305  if( !aFunc( zone ) )
306  return n;
307 
308  n++;
309  }
310  }
311  }
312 
313  if( typeMask[ PCB_FOOTPRINT_T ] )
314  {
315  if( !aFunc( footprint ) )
316  return n;
317 
318  n++;
319  }
320  }
321 
322  return n;
323 }
324 
325 
327 {
328 
329  if( const FP_TEXT* text = dyn_cast<const FP_TEXT*>( aItem ) )
330  {
331  if( !text->IsVisible() )
332  return true;
333  }
334 
335  if( const PCB_TEXT* text = dyn_cast<const PCB_TEXT*>( aItem ) )
336  {
337  if( !text->IsVisible() )
338  return true;
339  }
340 
341  return false;
342 }
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
ZONES & Zones()
Definition: board.h:302
bool ReportPhase(const wxString &aMessage)
bool isInvisibleText(const BOARD_ITEM *aItem) const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
std::vector< DRC_TEST_PROVIDER * > m_providers
constexpr KICAD_T BaseType(const KICAD_T aType)
Returns the underlying type of the given type.
Definition: typeinfo.h:235
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
virtual bool reportProgress(int aCount, int aSize, int aDelta)
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
virtual const wxString GetName() const
virtual void reportRuleStatistics()
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:125
LSET is a set of PCB_LAYER_IDs.
BOARD * GetBoard() const
Definition: drc_engine.h:87
virtual bool reportPhase(const wxString &aStageName)
std::unordered_map< const DRC_RULE *, int > m_stats
FOOTPRINTS & Footprints()
Definition: board.h:296
bool ReportProgress(double aProgress)
virtual void accountCheck(const DRC_RULE *ruleToTest)
ZONE handles a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:105
EDA_UNITS userUnits() const
virtual const wxString GetDescription() const
class DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:99
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
EDA_UNITS
Definition: eda_units.h:38
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, wxPoint aMarkerPos)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
DRC_TEST_PROVIDER is a base class that represents a DRC "provider" which runs some DRC functions over...
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:189
static std::vector< KICAD_T > s_allBasicItems
void ReportAux(const wxString &aStr)
static std::vector< KICAD_T > s_allBasicItemsButZones
DRC_ENGINE * m_drcEngine
class ZONE, managed by a footprint
Definition: typeinfo.h:94
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
EDA_UNITS UserUnits() const
Definition: drc_engine.h:151
Definition: pad.h:60
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, wxPoint aPos)
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
DRAWINGS & Drawings()
Definition: board.h:299
TRACKS & Tracks()
Definition: board.h:293
virtual void reportAux(wxString fmt,...)
Definition: track.h:83