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-2020 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 "miscellaneous";
64  };
65 
66  virtual const wxString GetDescription() const override
67  {
68  return "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 
116  m_msg.Printf( _( "(no edges found on Edge.Cuts layer)" ) );
117 
118  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
119  drcItem->SetItems( m_board );
120 
121  reportViolation( drcItem, m_board->GetBoundingBox().Centre() );
122  }
123  }
124 }
125 
126 
128 {
129  LSET disabledLayers = m_board->GetEnabledLayers().flip();
130 
131  // Perform the test only for copper layers
132  disabledLayers &= LSET::AllCuMask();
133 
134  auto checkDisabledLayers =
135  [&]( BOARD_ITEM* item ) -> bool
136  {
137  PCB_LAYER_ID badLayer = UNDEFINED_LAYER;
138 
139  if( item->Type() == PCB_PAD_T )
140  {
141  PAD* pad = static_cast<PAD*>( item );
142 
143  if( pad->GetAttribute() == PAD_ATTRIB::SMD
144  || pad->GetAttribute() == PAD_ATTRIB::CONN )
145  {
146  if( disabledLayers.test( item->GetLayer() ) )
147  badLayer = item->GetLayer();
148  }
149  else
150  {
151  // Through hole pad is on whatever layers there are.
152  }
153  }
154  else if( item->Type() == PCB_VIA_T )
155  {
156  PCB_VIA* via = static_cast<PCB_VIA*>( item );
157  PCB_LAYER_ID top;
158  PCB_LAYER_ID bottom;
159 
160  via->LayerPair( &top, &bottom );
161 
162  if( disabledLayers.test( top ) )
163  badLayer = top;
164  else if( disabledLayers.test( bottom ) )
165  badLayer = bottom;
166  }
167  else if( item->Type() == PCB_FP_ZONE_T )
168  {
169  // Footprint zones just get a top/bottom/inner setting, so they're on
170  // whatever inner layers there are.
171  }
172  else
173  {
174  LSET badLayers = disabledLayers & item->GetLayerSet();
175 
176  if( badLayers.any() )
177  badLayer = badLayers.Seq().front();
178  }
179 
180  if( badLayer != UNDEFINED_LAYER )
181  {
182  std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM );
183 
184  m_msg.Printf( _( "(layer %s)" ), LayerName( badLayer ) );
185 
186  drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
187  drcItem->SetItems( item );
188 
189  reportViolation( drcItem, item->GetPosition() );
190  }
191 
192  return true;
193  };
194 
195  forEachGeometryItem( s_allBasicItems, LSET::AllLayersMask(), checkDisabledLayers );
196 }
197 
198 
200 {
201  auto checkUnresolvedTextVar =
202  [&]( EDA_ITEM* item ) -> bool
203  {
205  return false;
206 
207  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item );
208 
209  if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
210  {
211  std::shared_ptr<DRC_ITEM>drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
212  drcItem->SetItems( item );
213 
214  reportViolation( drcItem, item->GetPosition() );
215  }
216  return true;
217  };
218 
220  checkUnresolvedTextVar );
221 
223  DS_DRAW_ITEM_LIST drawItems;
224 
226  return;
227 
228  drawItems.SetMilsToIUfactor( IU_PER_MILS );
229  drawItems.SetPageNumber( "1" );
230  drawItems.SetSheetCount( 1 );
231  drawItems.SetFileName( "dummyFilename" );
232  drawItems.SetSheetName( "dummySheet" );
233  drawItems.SetSheetLayer( "dummyLayer" );
234  drawItems.SetProject( m_board->GetProject() );
235  drawItems.BuildDrawItemsList( drawingSheet->GetPageInfo(), drawingSheet->GetTitleBlock() );
236 
237  for( DS_DRAW_ITEM_BASE* item = drawItems.GetFirst(); item; item = drawItems.GetNext() )
238  {
240  break;
241 
242  DS_DRAW_ITEM_TEXT* text = dynamic_cast<DS_DRAW_ITEM_TEXT*>( item );
243 
244  if( text && text->GetShownText().Matches( wxT( "*${*}*" ) ) )
245  {
246  std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE );
247  drcItem->SetItems( text );
248 
249  reportViolation( drcItem, text->GetPosition() );
250  }
251  }
252 }
253 
254 
256 {
258 
260  {
261  if( !reportPhase( _( "Checking board outline..." ) ) )
262  return false; // DRC cancelled
263 
264  testOutline();
265  }
266 
268  {
269  if( !reportPhase( _( "Checking disabled layers..." ) ) )
270  return false; // DRC cancelled
271 
273  }
274 
276  {
277  if( !reportPhase( _( "Checking text variables..." ) ) )
278  return false; // DRC cancelled
279 
280  testTextVars();
281  }
282 
283  return true;
284 }
285 
286 
288 {
289  return 3;
290 }
291 
292 
293 std::set<DRC_CONSTRAINT_T> DRC_TEST_PROVIDER_MISC::GetConstraintTypes() const
294 {
295  return {};
296 }
297 
298 
299 namespace detail
300 {
302 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:750
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: board.h:723
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:260
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:360
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
virtual std::set< DRC_CONSTRAINT_T > GetConstraintTypes() const override
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 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:119
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:504
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:27
static LSET AllLayersMask()
Definition: lset.cpp:787
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:190
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:136
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:100
wxPoint Centre() const
Definition: eda_rect.h:55
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
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)