KiCad PCB EDA Suite
drc_test_provider_misc.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) 2004-2023 KiCad Developers.
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
25#include <drc/drc_engine.h>
26#include <drc/drc_item.h>
27#include <drc/drc_rule.h>
30#include <pad.h>
31#include <pcb_track.h>
32
35
36/*
37 Miscellaneous tests:
38
39 - DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer
40 - DRCE_INVALID_OUTLINE, ///< invalid board outline
41 - DRCE_UNRESOLVED_VARIABLE,
42 - DRCE_ASSERTION_FAILURE ///< user-defined assertions
43*/
44
46{
47public:
49 m_board( nullptr )
50 {
51 m_isRuleDriven = false;
52 }
53
55 {
56 }
57
58 virtual bool Run() override;
59
60 virtual const wxString GetName() const override
61 {
62 return wxT( "miscellaneous" );
63 };
64
65 virtual const wxString GetDescription() const override
66 {
67 return wxT( "Misc checks (board outline, missing textvars)" );
68 }
69
70private:
71 void testOutline();
72 void testDisabledLayers();
73 void testTextVars();
74 void testAssertions();
75
77};
78
79
81{
82 SHAPE_POLY_SET dummyOutline;
83 bool errorHandled = false;
84
85 OUTLINE_ERROR_HANDLER errorHandler =
86 [&]( const wxString& msg, BOARD_ITEM* itemA, BOARD_ITEM* itemB, const VECTOR2I& pt )
87 {
88 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
89
90 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
91 drcItem->SetItems( itemA, itemB );
92
93 reportViolation( drcItem, pt, Edge_Cuts );
94 errorHandled = true;
95 };
96
97 // Use the standard chaining epsilon here so that we report errors that might affect
98 // other tools (such as STEP export).
99 int chainingEpsilon = m_board->GetOutlinesChainingEpsilon();
100
102 chainingEpsilon, &errorHandler ) )
103 {
104 if( errorHandled )
105 {
106 // if there is an invalid outline, then there must be an outline
107 }
108 else
109 {
110 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
111 wxString msg;
112
113 msg.Printf( _( "(no edges found on Edge.Cuts layer)" ) );
114
115 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
116 drcItem->SetItems( m_board );
117
119 }
120 }
121}
122
123
125{
126 const int progressDelta = 2000;
127 int ii = 0;
128 int items = 0;
129
130 auto countItems =
131 [&]( BOARD_ITEM* item ) -> bool
132 {
133 ++items;
134 return true;
135 };
136
137 LSET disabledLayers = m_board->GetEnabledLayers().flip();
138
139 // Perform the test only for copper layers
140 disabledLayers &= LSET::AllCuMask();
141
142 auto checkDisabledLayers =
143 [&]( BOARD_ITEM* item ) -> bool
144 {
146 return false;
147
148 if( !reportProgress( ii++, items, progressDelta ) )
149 return false;
150
151 PCB_LAYER_ID badLayer = UNDEFINED_LAYER;
152
153 if( item->Type() == PCB_PAD_T )
154 {
155 PAD* pad = static_cast<PAD*>( item );
156
157 if( pad->GetAttribute() == PAD_ATTRIB::SMD
158 || pad->GetAttribute() == PAD_ATTRIB::CONN )
159 {
160 if( disabledLayers.test( pad->GetPrincipalLayer() ) )
161 badLayer = item->GetLayer();
162 }
163 else
164 {
165 // Through hole pad pierces all physical layers.
166 }
167 }
168 else if( item->Type() == PCB_VIA_T )
169 {
170 PCB_VIA* via = static_cast<PCB_VIA*>( item );
171 PCB_LAYER_ID top;
172 PCB_LAYER_ID bottom;
173
174 via->LayerPair( &top, &bottom );
175
176 if( disabledLayers.test( top ) )
177 badLayer = top;
178 else if( disabledLayers.test( bottom ) )
179 badLayer = bottom;
180 }
181 else if( item->Type() == PCB_FP_ZONE_T )
182 {
183 // Footprint zones just get a top/bottom/inner setting, so they're on
184 // whatever inner layers there are.
185 }
186 else
187 {
188 LSET badLayers = disabledLayers & item->GetLayerSet();
189
190 if( badLayers.any() )
191 badLayer = badLayers.Seq().front();
192 }
193
194 if( badLayer != UNDEFINED_LAYER )
195 {
197 wxString msg;
198
199 msg.Printf( _( "(layer %s)" ), LayerName( badLayer ) );
200
201 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
202 drcItem->SetItems( item );
203
204 reportViolation( drcItem, item->GetPosition(), UNDEFINED_LAYER );
205 }
206
207 return true;
208 };
209
212}
213
214
216{
217 const int progressDelta = 2000;
218 int ii = 0;
219 int items = 0;
220
221 auto countItems =
222 [&]( BOARD_ITEM* item ) -> bool
223 {
224 ++items;
225 return true;
226 };
227
228 auto checkAssertions =
229 [&]( BOARD_ITEM* item ) -> bool
230 {
232 return false;
233
234 if( !reportProgress( ii++, items, progressDelta ) )
235 return false;
236
238 [&]( const DRC_CONSTRAINT* c )
239 {
241 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " (" )
242 + c->GetName() + wxS( ")" ) );
243 drcItem->SetItems( item );
244
245 reportViolation( drcItem, item->GetPosition(), item->GetLayer() );
246 } );
247
248 return true;
249 };
250
251 forEachGeometryItem( {}, LSET::AllLayersMask(), countItems );
252 forEachGeometryItem( {}, LSET::AllLayersMask(), checkAssertions );
253}
254
255
257{
258 const int progressDelta = 2000;
259 int ii = 0;
260 int items = 0;
261
262 static const std::vector<KICAD_T> itemTypes = {
265 };
266
268 [&]( BOARD_ITEM* item ) -> bool
269 {
270 ++items;
271 return true;
272 } );
273
275 [&]( BOARD_ITEM* item ) -> bool
276 {
278 return false;
279
280 if( !reportProgress( ii++, items, progressDelta ) )
281 return false;
282
283 BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
284 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( boardItem );
285
286 wxCHECK( boardItem, false );
287
288 if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
289 {
290 std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
291 drcItem->SetItems( item );
292
293 reportViolation( drcItem, boardItem->GetPosition(), boardItem->GetLayer() );
294 }
295
296 return true;
297 } );
298
300 DS_DRAW_ITEM_LIST drawItems;
301
303 return;
304
306 drawItems.SetPageNumber( wxT( "1" ) );
307 drawItems.SetSheetCount( 1 );
308 drawItems.SetFileName( wxT( "dummyFilename" ) );
309 drawItems.SetSheetName( wxT( "dummySheet" ) );
310 drawItems.SetSheetLayer( wxT( "dummyLayer" ) );
311 drawItems.SetProject( m_board->GetProject() );
312 drawItems.BuildDrawItemsList( drawingSheet->GetPageInfo(), drawingSheet->GetTitleBlock() );
313
314 for( DS_DRAW_ITEM_BASE* item = drawItems.GetFirst(); item; item = drawItems.GetNext() )
315 {
317 break;
318
319 if( m_drcEngine->IsCancelled() )
320 return;
321
322 DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item );
323
324 if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
325 {
326 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
327 drcItem->SetItems( drawingSheet );
328
329 reportViolation( drcItem, text->GetPosition(), LAYER_DRAWINGSHEET );
330 }
331 }
332}
333
334
336{
338
340 {
341 if( !reportPhase( _( "Checking board outline..." ) ) )
342 return false; // DRC cancelled
343
344 testOutline();
345 }
346
348 {
349 if( !reportPhase( _( "Checking disabled layers..." ) ) )
350 return false; // DRC cancelled
351
353 }
354
356 {
357 if( !reportPhase( _( "Checking text variables..." ) ) )
358 return false; // DRC cancelled
359
360 testTextVars();
361 }
362
364 {
365 if( !reportPhase( _( "Checking assertions..." ) ) )
366 return false; // DRC cancelled
367
369 }
370
371 return !m_drcEngine->IsCancelled();
372}
373
374
375namespace detail
376{
378}
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:70
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:192
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:269
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:587
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: board.h:828
int GetOutlinesChainingEpsilon()
Definition: board.h:668
PROJECT * GetProject() const
Definition: board.h:446
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:704
Vec Centre() const
Definition: box2.h:70
wxString GetName() const
Definition: drc_rule.h:149
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: drc_engine.h:98
BOARD * GetBoard() const
Definition: drc_engine.h:89
bool IsErrorLimitExceeded(int error_code)
void ProcessAssertions(const BOARD_ITEM *a, std::function< void(const DRC_CONSTRAINT *)> aFailureHandler, REPORTER *aReporter=nullptr)
bool IsCancelled() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:325
virtual const wxString GetName() const override
virtual const wxString GetDescription() const override
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out #DRC_ITEMs and po...
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)
static std::vector< KICAD_T > s_allBasicItems
DRC_ENGINE * m_drcEngine
Base class to handle basic graphic items.
Definition: ds_draw_item.h:59
Store the list of graphic items: rect, lines, polygons and texts to draw/plot the title block and fra...
Definition: ds_draw_item.h:385
DS_DRAW_ITEM_BASE * GetFirst()
Definition: ds_draw_item.h:483
void BuildDrawItemsList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Drawing or plot the drawing sheet.
void SetFileName(const wxString &aFileName)
Set the filename to draw/plot.
Definition: ds_draw_item.h:427
void SetSheetName(const wxString &aSheetName)
Set the sheet name to draw/plot.
Definition: ds_draw_item.h:432
void SetSheetLayer(const wxString &aSheetLayer)
Set the sheet layer to draw/plot.
Definition: ds_draw_item.h:442
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
Definition: ds_draw_item.h:470
void SetPageNumber(const wxString &aPageNumber)
Set the value of the sheet number.
Definition: ds_draw_item.h:460
DS_DRAW_ITEM_BASE * GetNext()
Definition: ds_draw_item.h:493
void SetMilsToIUfactor(double aMils2Iu)
Set the scalar to convert pages units (mils) to draw/plot units.
Definition: ds_draw_item.h:450
void SetProject(const PROJECT *aProject)
Definition: ds_draw_item.h:407
A graphic text.
Definition: ds_draw_item.h:303
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:249
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:532
static LSET AllLayersMask()
Definition: lset.cpp:808
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:773
Definition: pad.h:60
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition: pad.cpp:239
Represent a set of closed polygons.
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler)
Extracts the board outlines and build a closed polygon from lines, arcs and circle items on edge cut ...
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const VECTOR2I &pt)> OUTLINE_ERROR_HANDLER
@ DRCE_DISABLED_LAYER_ITEM
Definition: drc_item.h:67
@ DRCE_INVALID_OUTLINE
Definition: drc_item.h:68
@ DRCE_UNRESOLVED_VARIABLE
Definition: drc_item.h:81
@ DRCE_ASSERTION_FAILURE
Definition: drc_item.h:82
#define _(s)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition: layer_id.cpp:30
@ LAYER_DRAWINGSHEET
drawingsheet frame and titleblock
Definition: layer_ids.h:217
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ Edge_Cuts
Definition: layer_ids.h:113
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
@ SMD
Smd pad, appears on the solder paste layer (default)
@ CONN
Like smd, does not appear on the solder paste layer (default)
const double IU_PER_MILS
Definition: base_units.h:78
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:102
@ PCB_FP_TEXTBOX_T
class FP_TEXTBOX, wrapped text in a footprint
Definition: typeinfo.h:93
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:91
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:90
@ 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_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:105