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-2022 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 
24 #include <board_design_settings.h>
25 #include <drc/drc_engine.h>
26 #include <drc/drc_item.h>
27 #include <drc/drc_rule.h>
28 #include <drc/drc_test_provider.h>
29 #include <pad.h>
30 #include <pcb_track.h>
31 
34 
35 /*
36  Miscellaneous tests:
37 
38  - DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer
39  - DRCE_INVALID_OUTLINE, ///< invalid board outline
40  - DRCE_UNRESOLVED_VARIABLE,
41 
42  TODO:
43  - if grows too big, split into separate providers
44 */
45 
47 {
48 public:
50  m_board( nullptr )
51  {
52  m_isRuleDriven = false;
53  }
54 
56  {
57  }
58 
59  virtual bool Run() override;
60 
61  virtual const wxString GetName() const override
62  {
63  return wxT( "miscellaneous" );
64  };
65 
66  virtual const wxString GetDescription() const override
67  {
68  return wxT( "Misc checks (board outline, missing textvars)" );
69  }
70 
71  virtual std::set<DRC_CONSTRAINT_T> GetConstraintTypes() const override;
72 
73  int GetNumPhases() const override;
74 
75 private:
76  void testOutline();
77  void testDisabledLayers();
78  void testTextVars();
79 
81 };
82 
83 
85 {
86  SHAPE_POLY_SET dummyOutline;
87  bool errorHandled = false;
88 
89  OUTLINE_ERROR_HANDLER errorHandler =
90  [&]( const wxString& msg, BOARD_ITEM* itemA, BOARD_ITEM* itemB, const wxPoint& pt )
91  {
92  std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
93 
94  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
95  drcItem->SetItems( itemA, itemB );
96 
97  reportViolation( drcItem, pt );
98  errorHandled = true;
99  };
100 
101  // Use a really tight chaining epsilon here so that we report errors that might affect
102  // other tools (such as STEP export).
103  constexpr int chainingEpsilon = Millimeter2iu( 0.02 ) / 100;
104 
106  chainingEpsilon, &errorHandler ) )
107  {
108  if( errorHandled )
109  {
110  // if there is an invalid outline, then there must be an outline
111  }
112  else
113  {
114  std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
115  wxString msg;
116 
117  msg.Printf( _( "(no edges found on Edge.Cuts layer)" ) );
118 
119  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
120  drcItem->SetItems( m_board );
121 
122  reportViolation( drcItem, m_board->GetBoundingBox().Centre() );
123  }
124  }
125 }
126 
127 
129 {
130  // This is the number of tests between 2 calls to the progress bar
131  const int delta = 2000;
132 
133  int ii = 0;
134  int items = 0;
135 
136  auto countItems =
137  [&]( BOARD_ITEM* item ) -> bool
138  {
139  ++items;
140  return true;
141  };
142 
143  LSET disabledLayers = m_board->GetEnabledLayers().flip();
144 
145  // Perform the test only for copper layers
146  disabledLayers &= LSET::AllCuMask();
147 
148  auto checkDisabledLayers =
149  [&]( BOARD_ITEM* item ) -> bool
150  {
152  return false;
153 
154  if( !reportProgress( ii++, items, delta ) )
155  return false;
156 
157  PCB_LAYER_ID badLayer = UNDEFINED_LAYER;
158 
159  if( item->Type() == PCB_PAD_T )
160  {
161  PAD* pad = static_cast<PAD*>( item );
162 
163  if( pad->GetAttribute() == PAD_ATTRIB::SMD
164  || pad->GetAttribute() == PAD_ATTRIB::CONN )
165  {
166  if( disabledLayers.test( item->GetLayer() ) )
167  badLayer = item->GetLayer();
168  }
169  else
170  {
171  // Through hole pad is on whatever layers there are.
172  }
173  }
174  else if( item->Type() == PCB_VIA_T )
175  {
176  PCB_VIA* via = static_cast<PCB_VIA*>( item );
177  PCB_LAYER_ID top;
178  PCB_LAYER_ID bottom;
179 
180  via->LayerPair( &top, &bottom );
181 
182  if( disabledLayers.test( top ) )
183  badLayer = top;
184  else if( disabledLayers.test( bottom ) )
185  badLayer = bottom;
186  }
187  else if( item->Type() == PCB_FP_ZONE_T )
188  {
189  // Footprint zones just get a top/bottom/inner setting, so they're on
190  // whatever inner layers there are.
191  }
192  else
193  {
194  LSET badLayers = disabledLayers & item->GetLayerSet();
195 
196  if( badLayers.any() )
197  badLayer = badLayers.Seq().front();
198  }
199 
200  if( badLayer != UNDEFINED_LAYER )
201  {
202  std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM );
203  wxString msg;
204 
205  msg.Printf( _( "(layer %s)" ), LayerName( badLayer ) );
206 
207  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
208  drcItem->SetItems( item );
209 
210  reportViolation( drcItem, item->GetPosition() );
211  }
212 
213  return true;
214  };
215 
217  forEachGeometryItem( s_allBasicItems, LSET::AllLayersMask(), checkDisabledLayers );
218 }
219 
220 
222 {
223  // This is the number of tests between 2 calls to the progress bar
224  const int delta = 2000;
225 
226  int ii = 0;
227  int items = 0;
228 
229  static const std::vector<KICAD_T> itemTypes = {
232  };
233 
235  [&]( BOARD_ITEM* item ) -> bool
236  {
237  ++items;
238  return true;
239  } );
240 
242  [&]( BOARD_ITEM* item ) -> bool
243  {
245  return false;
246 
247  if( !reportProgress( ii++, items, delta ) )
248  return false;
249 
250  BOARD_ITEM* boardItem = dynamic_cast<BOARD_ITEM*>( item );
251  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( boardItem );
252 
253  if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
254  {
255  std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
256  drcItem->SetItems( item );
257 
258  reportViolation( drcItem, boardItem->GetPosition() );
259  }
260  return true;
261  } );
262 
264  DS_DRAW_ITEM_LIST drawItems;
265 
267  return;
268 
269  drawItems.SetMilsToIUfactor( IU_PER_MILS );
270  drawItems.SetPageNumber( wxT( "1" ) );
271  drawItems.SetSheetCount( 1 );
272  drawItems.SetFileName( wxT( "dummyFilename" ) );
273  drawItems.SetSheetName( wxT( "dummySheet" ) );
274  drawItems.SetSheetLayer( wxT( "dummyLayer" ) );
275  drawItems.SetProject( m_board->GetProject() );
276  drawItems.BuildDrawItemsList( drawingSheet->GetPageInfo(), drawingSheet->GetTitleBlock() );
277 
278  for( DS_DRAW_ITEM_BASE* item = drawItems.GetFirst(); item; item = drawItems.GetNext() )
279  {
281  break;
282 
283  DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item );
284 
285  if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
286  {
287  std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
288  drcItem->SetItems( text );
289 
290  reportViolation( drcItem, text->GetPosition() );
291  }
292  }
293 }
294 
295 
297 {
299 
301  {
302  if( !reportPhase( _( "Checking board outline..." ) ) )
303  return false; // DRC cancelled
304 
305  testOutline();
306  }
307 
309  {
310  if( !reportPhase( _( "Checking disabled layers..." ) ) )
311  return false; // DRC cancelled
312 
314  }
315 
317  {
318  if( !reportPhase( _( "Checking text variables..." ) ) )
319  return false; // DRC cancelled
320 
321  testTextVars();
322  }
323 
324  return true;
325 }
326 
327 
329 {
330  return 3;
331 }
332 
333 
334 std::set<DRC_CONSTRAINT_T> DRC_TEST_PROVIDER_MISC::GetConstraintTypes() const
335 {
336  return {};
337 }
338 
339 
340 namespace detail
341 {
343 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:759
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: board.h:724
DS_PROXY_VIEW_ITEM * GetDrawingSheet() const
Definition: drc_engine.h:97
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:266
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
void SetMilsToIUfactor(double aMils2Iu)
Set the scalar to convert pages units (mils) to draw/plot units.
Definition: ds_draw_item.h:442
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const wxPoint &aMarkerPos)
void SetFileName(const wxString &aFileName)
Set the filename to draw/plot.
Definition: ds_draw_item.h:415
bool IsErrorLimitExceeded(int error_code)
Like smd, does not appear on the solder paste layer (default)
Smd pad, appears on the solder paste layer (default)
PROJECT * GetProject() const
Definition: board.h:361
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
virtual std::set< DRC_CONSTRAINT_T > GetConstraintTypes() const override
virtual bool reportProgress(int aCount, int aSize, int aDelta)
class PAD, a pad in a footprint
Definition: typeinfo.h:89
LSET GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:467
virtual wxPoint GetPosition() const
Definition: eda_item.h:251
virtual const wxString GetDescription() const override
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
int GetNumPhases() const override
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:590
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:140
Base class to handle basic graphic items.
Definition: ds_draw_item.h:58
A graphic text.
Definition: ds_draw_item.h:297
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 ...
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:516
DS_DRAW_ITEM_BASE * GetNext()
Definition: ds_draw_item.h:494
BOARD * GetBoard() const
Definition: drc_engine.h:88
virtual bool reportPhase(const wxString &aStageName)
Represent a set of closed polygons.
void SetPageNumber(const wxString &aPageNumber)
Set the value of the sheet number.
Definition: ds_draw_item.h:455
virtual const wxString GetName() const override
#define _(s)
wxString LayerName(int aLayer)
Returns the default display name for a given layer.
Definition: layer_id.cpp:30
static LSET AllLayersMask()
Definition: lset.cpp:796
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:99
void SetSheetName(const wxString &aSheetName)
Set the sheet name to draw/plot.
Definition: ds_draw_item.h:423
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, LSET aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
void BuildDrawItemsList(const PAGE_INFO &aPageInfo, const TITLE_BLOCK &aTitleBlock)
Drawing or plot the drawing sheet.
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out #DRC_ITEMs and po...
void SetSheetLayer(const wxString &aSheetLayer)
Set the sheet layer to draw/plot.
Definition: ds_draw_item.h:431
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:191
static std::vector< KICAD_T > s_allBasicItems
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
DRC_ENGINE * m_drcEngine
class ZONE, managed by a footprint
Definition: typeinfo.h:94
void SetProject(const PROJECT *aProject)
Definition: ds_draw_item.h:400
#define IU_PER_MILS
Definition: plotter.cpp:130
wxPoint Centre() const
Definition: eda_rect.h:64
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
void SetSheetCount(int aSheetCount)
Set the value of the count of sheets, for basic inscriptions.
Definition: ds_draw_item.h:468
Store the list of graphic items: rect, lines, polygons and texts to draw/plot the title block and fra...
Definition: ds_draw_item.h:376
constexpr int delta
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const wxPoint &pt)> OUTLINE_ERROR_HANDLER
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
Definition: pad.h:57
DS_DRAW_ITEM_BASE * GetFirst()
Definition: ds_draw_item.h:484
static constexpr int Millimeter2iu(double mm)