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 (C) 2020-2024 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 m_commit (nullptr )
50{
51}
52
53
55{
56 if( s_allBasicItems.size() == 0 )
57 {
58 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
59 {
60 if( i != PCB_FOOTPRINT_T && i != PCB_GROUP_T )
61 {
62 s_allBasicItems.push_back( (KICAD_T) i );
63
64 if( i != PCB_ZONE_T )
65 s_allBasicItemsButZones.push_back( (KICAD_T) i );
66 }
67 }
68 }
69}
70
71
72const wxString DRC_TEST_PROVIDER::GetName() const { return wxT( "<no name test>" ); }
73const wxString DRC_TEST_PROVIDER::GetDescription() const { return wxEmptyString; }
74
75
76void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
77 const VECTOR2I& aMarkerPos, int aMarkerLayer )
78{
79 std::lock_guard<std::mutex> lock( m_statsMutex );
80 if( item->GetViolatingRule() )
81 accountCheck( item->GetViolatingRule() );
82
83 item->SetViolatingTest( this );
84 m_drcEngine->ReportViolation( item, aMarkerPos, aMarkerLayer );
85}
86
87
88bool DRC_TEST_PROVIDER::reportProgress( size_t aCount, size_t aSize, size_t aDelta )
89{
90 if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
91 {
92 if( !m_drcEngine->ReportProgress( static_cast<double>( aCount ) / aSize ) )
93 return false;
94 }
95
96 return true;
97}
98
99
100bool DRC_TEST_PROVIDER::reportPhase( const wxString& aMessage )
101{
102 reportAux( aMessage );
103 return m_drcEngine->ReportPhase( aMessage );
104}
105
106
107void DRC_TEST_PROVIDER::reportAux( const wxChar* fmt, ... )
108{
109 va_list vargs;
110 va_start( vargs, fmt );
111 wxString str;
112 str.PrintfV( fmt, vargs );
113 va_end( vargs );
114 m_drcEngine->ReportAux( str );
115}
116
117
119{
120 auto it = m_stats.find( ruleToTest );
121
122 if( it == m_stats.end() )
123 m_stats[ ruleToTest ] = 1;
124 else
125 m_stats[ ruleToTest ] += 1;
126}
127
128
129void DRC_TEST_PROVIDER::accountCheck( const DRC_CONSTRAINT& constraintToTest )
130{
131 accountCheck( constraintToTest.GetParentRule() );
132}
133
134
136{
137 if( !m_isRuleDriven )
138 return;
139
140 m_drcEngine->ReportAux( wxT( "Rule hit statistics: " ) );
141
142 for( const std::pair<const DRC_RULE* const, int>& stat : m_stats )
143 {
144 if( stat.first )
145 {
146 m_drcEngine->ReportAux( wxString::Format( wxT( " - rule '%s': %d hits " ),
147 stat.first->m_Name,
148 stat.second ) );
149 }
150 }
151}
152
153
154int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, LSET aLayers,
155 const std::function<bool( BOARD_ITEM*)>& aFunc )
156{
157 BOARD *brd = m_drcEngine->GetBoard();
158 std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
159 int n = 0;
160
161 if( aTypes.size() == 0 )
162 {
163 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
164 typeMask[ i ] = true;
165 }
166 else
167 {
168 for( KICAD_T aType : aTypes )
169 typeMask[ aType ] = true;
170 }
171
172 for( PCB_TRACK* item : brd->Tracks() )
173 {
174 if( (item->GetLayerSet() & aLayers).any() )
175 {
176 if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
177 {
178 aFunc( item );
179 n++;
180 }
181 else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
182 {
183 aFunc( item );
184 n++;
185 }
186 else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
187 {
188 aFunc( item );
189 n++;
190 }
191 }
192 }
193
194 for( BOARD_ITEM* item : brd->Drawings() )
195 {
196 if( (item->GetLayerSet() & aLayers).any() )
197 {
198 if( typeMask[ PCB_DIMENSION_T ] && BaseType( item->Type() ) == PCB_DIMENSION_T )
199 {
200 if( !aFunc( item ) )
201 return n;
202
203 n++;
204 }
205 else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T )
206 {
207 if( !aFunc( item ) )
208 return n;
209
210 n++;
211 }
212 else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
213 {
214 if( !aFunc( item ) )
215 return n;
216
217 n++;
218 }
219 else if( typeMask[ PCB_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T )
220 {
221 if( !aFunc( item ) )
222 return n;
223
224 n++;
225 }
226 else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
227 {
228 if( !aFunc( item ) )
229 return n;
230
231 n++;
232 }
233 }
234 }
235
236 if( typeMask[ PCB_ZONE_T ] )
237 {
238 for( ZONE* item : brd->Zones() )
239 {
240 if( ( item->GetLayerSet() & aLayers ).any() )
241 {
242 if( !aFunc( item ) )
243 return n;
244
245 n++;
246 }
247 }
248 }
249
250 for( FOOTPRINT* footprint : brd->Footprints() )
251 {
252 if( typeMask[ PCB_FIELD_T ] )
253 {
254 for( PCB_FIELD* field : footprint->GetFields() )
255 {
256 if( ( field->GetLayerSet() & aLayers ).any() )
257 {
258 if( !aFunc( field ) )
259 return n;
260
261 n++;
262 }
263 }
264 }
265
266 if( typeMask[ PCB_PAD_T ] )
267 {
268 for( PAD* pad : footprint->Pads() )
269 {
270 // Careful: if a pad has a hole then it pierces all layers
271 if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
272 {
273 if( !aFunc( pad ) )
274 return n;
275
276 n++;
277 }
278 }
279 }
280
281 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
282 {
283 if( (dwg->GetLayerSet() & aLayers).any() )
284 {
285 if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T )
286 {
287 if( !aFunc( dwg ) )
288 return n;
289
290 n++;
291 }
292 else if( typeMask[ PCB_TEXT_T ] && dwg->Type() == PCB_TEXT_T )
293 {
294 if( !aFunc( dwg ) )
295 return n;
296
297 n++;
298 }
299 else if( typeMask[ PCB_TEXTBOX_T ] && dwg->Type() == PCB_TEXTBOX_T )
300 {
301 if( !aFunc( dwg ) )
302 return n;
303
304 n++;
305 }
306 else if( typeMask[ PCB_SHAPE_T ] && dwg->Type() == PCB_SHAPE_T )
307 {
308 if( !aFunc( dwg ) )
309 return n;
310
311 n++;
312 }
313 }
314 }
315
316 if( typeMask[ PCB_ZONE_T ] )
317 {
318 for( ZONE* zone : footprint->Zones() )
319 {
320 if( (zone->GetLayerSet() & aLayers).any() )
321 {
322 if( !aFunc( zone ) )
323 return n;
324
325 n++;
326 }
327 }
328 }
329
330 if( typeMask[ PCB_FOOTPRINT_T ] )
331 {
332 if( !aFunc( footprint ) )
333 return n;
334
335 n++;
336 }
337 }
338
339 return n;
340}
341
342
344{
345 if( const PCB_TEXT* text = dynamic_cast<const PCB_TEXT*>( aItem ) )
346 {
347 if( !text->IsVisible() )
348 return true;
349 }
350
351 return false;
352}
353
354
355wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
356 double aConstraint, double aActual )
357{
358 wxString constraint_str = MessageTextFromValue( aConstraint );
359 wxString actual_str = MessageTextFromValue( aActual );
360
361 if( constraint_str == actual_str )
362 {
363 // Use more precise formatting if the message-text strings were equal.
364 constraint_str = StringFromValue( aConstraint, true );
365 actual_str = StringFromValue( aActual, true );
366 }
367
368 return wxString::Format( aFormatString, aSource, constraint_str, actual_str );
369}
370
371wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
372 const EDA_ANGLE& aConstraint, const EDA_ANGLE& aActual )
373{
374 wxString constraint_str = MessageTextFromValue( aConstraint );
375 wxString actual_str = MessageTextFromValue( aActual );
376
377 if( constraint_str == actual_str )
378 {
379 // Use more precise formatting if the message-text strings were equal.
380 constraint_str = StringFromValue( aConstraint, true );
381 actual_str = StringFromValue( aActual, true );
382 }
383
384 return wxString::Format( aFormatString, aSource, constraint_str, actual_str );
385}
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:290
const ZONES & Zones() const
Definition: board.h:335
const FOOTPRINTS & Footprints() const
Definition: board.h:331
const TRACKS & Tracks() const
Definition: board.h:329
const DRAWINGS & Drawings() const
Definition: board.h:333
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:156
BOARD * GetBoard() const
Definition: drc_engine.h:99
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_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)
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:36
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
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