KiCad PCB EDA Suite
drc_test_provider_silk_clearance.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 <common.h>
25#include <board.h>
26#include <footprint.h>
27#include <pcb_shape.h>
28#include <pcb_track.h>
29#include <pad.h>
31#include <geometry/seg.h>
32#include <drc/drc_engine.h>
33#include <drc/drc_item.h>
34#include <drc/drc_rule.h>
36#include <drc/drc_rtree.h>
37
38/*
39 Silk to silk clearance test. Check all silkscreen features against each other.
40 Errors generated:
41 - DRCE_OVERLAPPING_SILK
42
43*/
44
46{
47public:
49 m_board( nullptr ),
51 {
52 }
53
55 {
56 }
57
58 virtual bool Run() override;
59
60 virtual const wxString GetName() const override
61 {
62 return wxT( "silk_clearance" );
63 };
64
65 virtual const wxString GetDescription() const override
66 {
67 return wxT( "Tests for overlapping silkscreen features." );
68 }
69
70private:
71
74};
75
76
78{
79 const int progressDelta = 500;
80
82 {
83 reportAux( wxT( "Overlapping silk violations ignored. Tests not run." ) );
84 return true; // continue with other tests
85 }
86
88
89 DRC_CONSTRAINT worstClearanceConstraint;
91
92 if( m_drcEngine->QueryWorstConstraint( SILK_CLEARANCE_CONSTRAINT, worstClearanceConstraint ) )
93 m_largestClearance = worstClearanceConstraint.m_Value.Min();
94
95 reportAux( wxT( "Worst clearance : %d nm" ), m_largestClearance );
96
97 if( !reportPhase( _( "Checking silkscreen for overlapping items..." ) ) )
98 return false; // DRC cancelled
99
100 DRC_RTREE silkTree;
101 DRC_RTREE targetTree;
102 int ii = 0;
103 int items = 0;
104
105 auto countItems =
106 [&]( BOARD_ITEM* item ) -> bool
107 {
108 ++items;
109 return true;
110 };
111
112 auto addToSilkTree =
113 [&]( BOARD_ITEM* item ) -> bool
114 {
115 if( !reportProgress( ii++, items, progressDelta ) )
116 return false;
117
118 for( PCB_LAYER_ID layer : { F_SilkS, B_SilkS } )
119 {
120 if( item->IsOnLayer( layer ) )
121 silkTree.Insert( item, layer );
122 }
123
124 return true;
125 };
126
127 auto addToTargetTree =
128 [&]( BOARD_ITEM* item ) -> bool
129 {
130 if( !reportProgress( ii++, items, progressDelta ) )
131 return false;
132
133 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
134 targetTree.Insert( item, layer );
135
136 return true;
137 };
138
140
143 countItems );
144
145 forEachGeometryItem( s_allBasicItems, LSET( 2, F_SilkS, B_SilkS ), addToSilkTree );
146
149 addToTargetTree );
150
151 reportAux( wxT( "Testing %d silkscreen features against %d board items." ),
152 silkTree.size(),
153 targetTree.size() );
154
155 const std::vector<DRC_RTREE::LAYER_PAIR> layerPairs =
156 {
175 };
176
177 targetTree.QueryCollidingPairs( &silkTree, layerPairs,
178 [&]( const DRC_RTREE::LAYER_PAIR& aLayers, DRC_RTREE::ITEM_WITH_SHAPE* aRefItemShape,
179 DRC_RTREE::ITEM_WITH_SHAPE* aTestItemShape, bool* aCollisionDetected ) -> bool
180 {
181 BOARD_ITEM* refItem = aRefItemShape->parent;
182 const SHAPE* refShape = aRefItemShape->shape;
183 BOARD_ITEM* testItem = aTestItemShape->parent;
184 const SHAPE* testShape = aTestItemShape->shape;
185
186 std::shared_ptr<SHAPE> hole;
187
189 return false;
190
191 if( isInvisibleText( refItem ) || isInvisibleText( testItem ) )
192 return true;
193
194 if( testItem->IsTented() )
195 {
196 if( testItem->HasHole() )
197 {
198 hole = testItem->GetEffectiveHoleShape();
199 testShape = hole.get();
200 }
201 else
202 {
203 return true;
204 }
205 }
206
208 refItem, testItem,
209 aLayers.second );
210
211 if( constraint.IsNull() || constraint.GetSeverity() == RPT_SEVERITY_IGNORE )
212 return true;
213
214 int minClearance = constraint.GetValue().Min();
215
216 if( minClearance < 0 )
217 return true;
218
219 int actual;
220 VECTOR2I pos;
221
222 // Graphics are often compound shapes so ignore collisions between shapes in a
223 // single footprint or on the board.
224 if( refItem->Type() == PCB_SHAPE_T && testItem->Type() == PCB_SHAPE_T )
225 {
226 return true;
227 }
228 else if( refItem->Type() == PCB_FP_SHAPE_T && testItem->Type() == PCB_FP_SHAPE_T
229 && refItem->GetParentFootprint() == testItem->GetParentFootprint() )
230 {
231 return true;
232 }
233
234 if( refShape->Collide( testShape, minClearance, &actual, &pos ) )
235 {
236 std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_SILK );
237
238 if( minClearance > 0 )
239 {
240 wxString msg = formatMsg( _( "(%s clearance %s; actual %s)" ),
241 constraint.GetParentRule()->m_Name,
242 minClearance,
243 actual );
244
245 drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + msg );
246 }
247
248 drcItem->SetItems( refItem, testItem );
249 drcItem->SetViolatingRule( constraint.GetParentRule() );
250
251 reportViolation( drcItem, pos, aLayers.second );
252
253 *aCollisionDetected = true;
254 }
255
256 return true;
257 },
258 m_largestClearance,
259 [&]( int aCount, int aSize ) -> bool
260 {
261 return reportProgress( aCount, aSize, progressDelta );
262 } );
263
264 reportRuleStatistics();
265
266 return !m_drcEngine->IsCancelled();
267}
268
269
270namespace detail
271{
273}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:58
virtual bool IsTented() const
Definition: board_item.h:133
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:265
SEVERITY GetSeverity() const
Definition: drc_rule.h:160
const MINOPTMAX< int > & GetValue() const
Definition: drc_rule.h:139
MINOPTMAX< int > m_Value
Definition: drc_rule.h:170
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:143
bool IsNull() const
Definition: drc_rule.h:134
BOARD * GetBoard() const
Definition: drc_engine.h:89
bool IsErrorLimitExceeded(int error_code)
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
Definition: drc_engine.cpp:671
bool QueryWorstConstraint(DRC_CONSTRAINT_T aRuleId, DRC_CONSTRAINT &aConstraint)
Implement an R-tree for fast spatial and layer indexing of connectable items.
Definition: drc_rtree.h:48
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, int aWorstClearance=0)
Insert an item into the tree on a particular layer with an optional worst clearance.
Definition: drc_rtree.h:104
size_t size() const
Return the number of items in the tree.
Definition: drc_rtree.h:507
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
Definition: drc_rtree.h:415
int QueryCollidingPairs(DRC_RTREE *aRefTree, std::vector< LAYER_PAIR > aLayerPairs, std::function< bool(const LAYER_PAIR &, ITEM_WITH_SHAPE *, ITEM_WITH_SHAPE *, bool *aCollision)> aVisitor, int aMaxClearance, std::function< bool(int, int)> aProgressReporter) const
Definition: drc_rtree.h:430
virtual const wxString GetName() const override
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
virtual const wxString GetDescription() const override
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)
virtual void reportAux(wxString fmt,...)
static std::vector< KICAD_T > s_allBasicItems
DRC_ENGINE * m_drcEngine
bool isInvisibleText(const BOARD_ITEM *aItem) const
LSET is a set of PCB_LAYER_IDs.
Definition: layer_ids.h:530
static LSET FrontMask()
Return a mask holding all technical layers and the external CU layer on front side.
Definition: lset.cpp:895
static LSET BackMask()
Return a mask holding all technical layers and the external CU layer on back side.
Definition: lset.cpp:902
T Min() const
Definition: minoptmax.h:33
An abstract shape on 2D plane.
Definition: shape.h:123
The common library.
@ DRCE_OVERLAPPING_SILK
Definition: drc_item.h:93
@ SILK_CLEARANCE_CONSTRAINT
Definition: drc_rule.h:52
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59
@ F_CrtYd
Definition: layer_ids.h:117
@ B_Adhes
Definition: layer_ids.h:97
@ Edge_Cuts
Definition: layer_ids.h:113
@ F_Paste
Definition: layer_ids.h:101
@ F_Adhes
Definition: layer_ids.h:98
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ B_Paste
Definition: layer_ids.h:100
@ F_Fab
Definition: layer_ids.h:120
@ Margin
Definition: layer_ids.h:114
@ F_SilkS
Definition: layer_ids.h:104
@ B_CrtYd
Definition: layer_ids.h:116
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
@ B_Fab
Definition: layer_ids.h:119
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
@ RPT_SEVERITY_IGNORE
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94