KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 The 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_item.h>
26#include <pcb_track.h>
27#include <footprint.h>
28#include <pad.h>
29#include <zone.h>
30#include <pcb_text.h>
31
32
33// A list of all basic (ie: non-compound) board geometry items
34std::vector<KICAD_T> DRC_TEST_PROVIDER::s_allBasicItems;
36
37
39{
40 for( DRC_TEST_PROVIDER* provider : m_providers )
41 delete provider;
42}
43
44
46 UNITS_PROVIDER( pcbIUScale, EDA_UNITS::MILLIMETRES ), m_drcEngine( nullptr )
47{
48}
49
50
52{
53 if( s_allBasicItems.size() == 0 )
54 {
55 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
56 {
57 if( i != PCB_FOOTPRINT_T && i != PCB_GROUP_T )
58 {
59 s_allBasicItems.push_back( (KICAD_T) i );
60
61 if( i != PCB_ZONE_T )
62 s_allBasicItemsButZones.push_back( (KICAD_T) i );
63 }
64 }
65 }
66}
67
68
69const wxString DRC_TEST_PROVIDER::GetName() const { return wxT( "<no name test>" ); }
70const wxString DRC_TEST_PROVIDER::GetDescription() const { return wxEmptyString; }
71
72
73void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
74 const VECTOR2I& aMarkerPos, int aMarkerLayer,
75 DRC_CUSTOM_MARKER_HANDLER* aCustomHandler )
76{
77 std::lock_guard<std::mutex> lock( m_statsMutex );
78 if( item->GetViolatingRule() )
79 accountCheck( item->GetViolatingRule() );
80
81 item->SetViolatingTest( this );
82 m_drcEngine->ReportViolation( item, aMarkerPos, aMarkerLayer, aCustomHandler );
83}
84
85
86bool DRC_TEST_PROVIDER::reportProgress( size_t aCount, size_t aSize, size_t aDelta )
87{
88 if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
89 {
90 if( !m_drcEngine->ReportProgress( static_cast<double>( aCount ) / 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( const wxChar* 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_FIELD_T ] )
251 {
252 for( PCB_FIELD* field : footprint->GetFields() )
253 {
254 if( ( field->GetLayerSet() & aLayers ).any() )
255 {
256 if( !aFunc( field ) )
257 return n;
258
259 n++;
260 }
261 }
262 }
263
264 if( typeMask[ PCB_PAD_T ] )
265 {
266 for( PAD* pad : footprint->Pads() )
267 {
268 // Careful: if a pad has a hole then it pierces all layers
269 if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
270 {
271 if( !aFunc( pad ) )
272 return n;
273
274 n++;
275 }
276 }
277 }
278
279 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
280 {
281 if( (dwg->GetLayerSet() & aLayers).any() )
282 {
283 if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T )
284 {
285 if( !aFunc( dwg ) )
286 return n;
287
288 n++;
289 }
290 else if( typeMask[ PCB_TEXT_T ] && dwg->Type() == PCB_TEXT_T )
291 {
292 if( !aFunc( dwg ) )
293 return n;
294
295 n++;
296 }
297 else if( typeMask[ PCB_TEXTBOX_T ] && dwg->Type() == PCB_TEXTBOX_T )
298 {
299 if( !aFunc( dwg ) )
300 return n;
301
302 n++;
303 }
304 else if( typeMask[ PCB_SHAPE_T ] && dwg->Type() == PCB_SHAPE_T )
305 {
306 if( !aFunc( dwg ) )
307 return n;
308
309 n++;
310 }
311 }
312 }
313
314 if( typeMask[ PCB_ZONE_T ] )
315 {
316 for( ZONE* zone : footprint->Zones() )
317 {
318 if( (zone->GetLayerSet() & aLayers).any() )
319 {
320 if( !aFunc( zone ) )
321 return n;
322
323 n++;
324 }
325 }
326 }
327
328 if( typeMask[ PCB_FOOTPRINT_T ] )
329 {
330 if( !aFunc( footprint ) )
331 return n;
332
333 n++;
334 }
335 }
336
337 return n;
338}
339
340
342{
343 if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aItem ) )
344 {
345 if( !text->IsVisible() )
346 return true;
347 }
348
349 return false;
350}
351
352
353wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
354 double aConstraint, double aActual )
355{
356 wxString constraint_str = MessageTextFromValue( aConstraint );
357 wxString actual_str = MessageTextFromValue( aActual );
358
359 if( constraint_str == actual_str )
360 {
361 // Use more precise formatting if the message-text strings were equal.
362 constraint_str = StringFromValue( aConstraint, true );
363 actual_str = StringFromValue( aActual, true );
364 }
365
366 return wxString::Format( aFormatString, aSource, constraint_str, actual_str );
367}
368
369wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
370 const EDA_ANGLE& aConstraint, const EDA_ANGLE& aActual )
371{
372 wxString constraint_str = MessageTextFromValue( aConstraint );
373 wxString actual_str = MessageTextFromValue( aActual );
374
375 if( constraint_str == actual_str )
376 {
377 // Use more precise formatting if the message-text strings were equal.
378 constraint_str = StringFromValue( aConstraint, true );
379 actual_str = StringFromValue( aActual, true );
380 }
381
382 return wxString::Format( aFormatString, aSource, constraint_str, actual_str );
383}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:295
const ZONES & Zones() const
Definition: board.h:340
const FOOTPRINTS & Footprints() const
Definition: board.h:336
const TRACKS & Tracks() const
Definition: board.h:334
const DRAWINGS & Drawings() const
Definition: board.h:338
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:156
void ReportViolation(const std::shared_ptr< DRC_ITEM > &aItem, const VECTOR2I &aPos, int aMarkerLayer, DRC_CUSTOM_MARKER_HANDLER *aCustomHandler=nullptr)
BOARD * GetBoard() const
Definition: drc_engine.h:96
bool ReportProgress(double aProgress)
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_ITEM and posi...
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual)
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 void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, DRC_CUSTOM_MARKER_HANDLER *aCustomHandler=nullptr)
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
void reportAux(const wxString &aMsg)
virtual void accountCheck(const DRC_RULE *ruleToTest)
virtual const wxString GetName() const
virtual void reportRuleStatistics()
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
Definition: pad.h:54
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString StringFromValue(double aValue, bool aAddUnitLabel=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
Converts aValue in internal units into a united string.
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
std::function< void(PCB_MARKER *aMarker)> DRC_CUSTOM_MARKER_HANDLER
Definition: drc_engine.h:69
EDA_UNITS
Definition: eda_units.h:46
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition: typeinfo.h:249
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_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ MAX_STRUCT_TYPE_ID
Definition: typeinfo.h:237
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96