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-2022 KiCad Developers, see AUTHORS.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>
27#include <pcb_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
35std::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
48 m_drcEngine( nullptr )
49{
50}
51
52
54{
55 if( s_allBasicItems.size() == 0 )
56 {
57 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
58 {
59 if( i != PCB_FOOTPRINT_T && i != PCB_GROUP_T )
60 {
61 s_allBasicItems.push_back( (KICAD_T) i );
62
63 if( i != PCB_ZONE_T && i != PCB_FP_ZONE_T )
64 s_allBasicItemsButZones.push_back( (KICAD_T) i );
65 }
66 }
67 }
68}
69
70
71const wxString DRC_TEST_PROVIDER::GetName() const { return wxT( "<no name test>" ); }
72const wxString DRC_TEST_PROVIDER::GetDescription() const { return wxEmptyString; }
73
74
75void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
76 const VECTOR2I& aMarkerPos, int aMarkerLayer )
77{
78 if( item->GetViolatingRule() )
79 accountCheck( item->GetViolatingRule() );
80
81 item->SetViolatingTest( this );
82 m_drcEngine->ReportViolation( item, aMarkerPos, aMarkerLayer );
83}
84
85
86bool DRC_TEST_PROVIDER::reportProgress( int aCount, int aSize, int aDelta )
87{
88 if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
89 {
90 if( !m_drcEngine->ReportProgress( (double) aCount / (double) aSize ) )
91 return false;
92 }
93
94 return true;
95}
96
97
98bool DRC_TEST_PROVIDER::reportPhase( const wxString& aMessage )
99{
100 reportAux( aMessage );
101 return m_drcEngine->ReportPhase( aMessage );
102}
103
104
105void DRC_TEST_PROVIDER::reportAux( wxString fmt, ... )
106{
107 va_list vargs;
108 va_start( vargs, fmt );
109 wxString str;
110 str.PrintfV( fmt, vargs );
111 va_end( vargs );
112 m_drcEngine->ReportAux( str );
113}
114
115
117{
118 auto it = m_stats.find( ruleToTest );
119
120 if( it == m_stats.end() )
121 m_stats[ ruleToTest ] = 1;
122 else
123 m_stats[ ruleToTest ] += 1;
124}
125
126
127void DRC_TEST_PROVIDER::accountCheck( const DRC_CONSTRAINT& constraintToTest )
128{
129 accountCheck( constraintToTest.GetParentRule() );
130}
131
132
134{
135 if( !m_isRuleDriven )
136 return;
137
138 m_drcEngine->ReportAux( wxT( "Rule hit statistics: " ) );
139
140 for( const std::pair<const DRC_RULE* const, int>& stat : m_stats )
141 {
142 if( stat.first )
143 {
144 m_drcEngine->ReportAux( wxString::Format( wxT( " - rule '%s': %d hits " ),
145 stat.first->m_Name,
146 stat.second ) );
147 }
148 }
149}
150
151
152int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, LSET aLayers,
153 const std::function<bool( BOARD_ITEM*)>& aFunc )
154{
155 BOARD *brd = m_drcEngine->GetBoard();
156 std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
157 int n = 0;
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( PCB_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_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T )
218 {
219 if( !aFunc( item ) )
220 return n;
221
222 n++;
223 }
224 else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
225 {
226 if( !aFunc( item ) )
227 return n;
228
229 n++;
230 }
231 }
232 }
233
234 if( typeMask[ PCB_ZONE_T ] )
235 {
236 for( ZONE* item : brd->Zones() )
237 {
238 if( ( item->GetLayerSet() & aLayers ).any() )
239 {
240 if( !aFunc( item ) )
241 return n;
242
243 n++;
244 }
245 }
246 }
247
248 for( FOOTPRINT* footprint : brd->Footprints() )
249 {
250 if( typeMask[ PCB_FP_TEXT_T ] )
251 {
252 if( ( footprint->Reference().GetLayerSet() & aLayers ).any() )
253 {
254 if( !aFunc( &footprint->Reference() ) )
255 return n;
256
257 n++;
258 }
259
260 if( ( footprint->Value().GetLayerSet() & aLayers ).any() )
261 {
262 if( !aFunc( &footprint->Value() ) )
263 return n;
264
265 n++;
266 }
267 }
268
269 if( typeMask[ PCB_PAD_T ] )
270 {
271 for( PAD* pad : footprint->Pads() )
272 {
273 // Careful: if a pad has a hole then it pierces all layers
274 if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
275 {
276 if( !aFunc( pad ) )
277 return n;
278
279 n++;
280 }
281 }
282 }
283
284 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
285 {
286 if( (dwg->GetLayerSet() & aLayers).any() )
287 {
288 if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T )
289 {
290 if( !aFunc( dwg ) )
291 return n;
292
293 n++;
294 }
295 else if( typeMask[ PCB_FP_TEXT_T ] && dwg->Type() == PCB_FP_TEXT_T )
296 {
297 if( !aFunc( dwg ) )
298 return n;
299
300 n++;
301 }
302 else if( typeMask[ PCB_FP_TEXTBOX_T ] && dwg->Type() == PCB_FP_TEXTBOX_T )
303 {
304 if( !aFunc( dwg ) )
305 return n;
306
307 n++;
308 }
309 else if( typeMask[ PCB_FP_SHAPE_T ] && dwg->Type() == PCB_FP_SHAPE_T )
310 {
311 if( !aFunc( dwg ) )
312 return n;
313
314 n++;
315 }
316 }
317 }
318
319 if( typeMask[ PCB_FP_ZONE_T ] )
320 {
321 for( ZONE* zone : footprint->Zones() )
322 {
323 if( (zone->GetLayerSet() & aLayers).any() )
324 {
325 if( !aFunc( zone ) )
326 return n;
327
328 n++;
329 }
330 }
331 }
332
333 if( typeMask[ PCB_FOOTPRINT_T ] )
334 {
335 if( !aFunc( footprint ) )
336 return n;
337
338 n++;
339 }
340 }
341
342 return n;
343}
344
345
347{
348
349 if( const FP_TEXT* text = dyn_cast<const FP_TEXT*>( aItem ) )
350 {
351 if( !text->IsVisible() )
352 return true;
353 }
354
355 if( const PCB_TEXT* text = dyn_cast<const PCB_TEXT*>( aItem ) )
356 {
357 if( !text->IsVisible() )
358 return true;
359 }
360
361 return false;
362}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
ZONES & Zones()
Definition: board.h:313
FOOTPRINTS & Footprints()
Definition: board.h:307
TRACKS & Tracks()
Definition: board.h:304
DRAWINGS & Drawings()
Definition: board.h:310
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:143
BOARD * GetBoard() const
Definition: drc_engine.h:89
bool ReportProgress(double aProgress)
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer)
void ReportAux(const wxString &aStr)
bool ReportPhase(const wxString &aMessage)
std::vector< DRC_TEST_PROVIDER * > m_providers
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out #DRC_ITEMs and po...
static std::vector< KICAD_T > s_allBasicItemsButZones
virtual bool reportPhase(const wxString &aStageName)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
virtual bool reportProgress(int aCount, int aSize, int aDelta)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer)
virtual void reportAux(wxString fmt,...)
static std::vector< KICAD_T > s_allBasicItems
virtual const wxString GetDescription() const
DRC_ENGINE * m_drcEngine
bool isInvisibleText(const BOARD_ITEM *aItem) const
std::unordered_map< const DRC_RULE *, int > m_stats
virtual void accountCheck(const DRC_RULE *ruleToTest)
virtual const wxString GetName() const
virtual void reportRuleStatistics()
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
Definition: pad.h:58
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
EDA_UNITS
Definition: eda_units.h:43
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
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:253
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ MAX_STRUCT_TYPE_ID
Definition: typeinfo.h:241
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:115
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:112
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:111
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_FP_ZONE_T
class ZONE, managed by a footprint
Definition: typeinfo.h:100
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:103
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:105
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:101