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 The 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 "pcb_table.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
44
45
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>" ); }
73
74
75void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
76 const VECTOR2I& aMarkerPos, int aMarkerLayer,
77 const std::function<void( PCB_MARKER* )>& aPathGenerator )
78{
79 item->SetViolatingTest( this );
80 m_drcEngine->ReportViolation( item, aMarkerPos, aMarkerLayer, aPathGenerator );
81}
82
83
84void DRC_TEST_PROVIDER::reportTwoPointGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
85 const VECTOR2I& ptA, const VECTOR2I& ptB, PCB_LAYER_ID aLayer )
86{
87 PCB_SHAPE ptAShape( nullptr, SHAPE_T::SEGMENT );
88 ptAShape.SetStart( ptA );
89 ptAShape.SetEnd( ptB );
90
91 reportViolation( aDrcItem, aMarkerPos, aLayer,
92 [&]( PCB_MARKER* aMarker )
93 {
94 aMarker->SetPath( { ptAShape }, ptA, ptB );
95 } );
96}
97
98
99void DRC_TEST_PROVIDER::reportTwoShapeGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
100 const SHAPE* aShape1, const SHAPE* aShape2, PCB_LAYER_ID aLayer,
101 int aDistance )
102{
103 VECTOR2I ptA, ptB;
104
105 if( aDistance == 0 )
106 {
107 reportTwoPointGeometry( aDrcItem, aMarkerPos, aMarkerPos, aMarkerPos, aLayer );
108 }
109 else if( aShape1->NearestPoints( aShape2, ptA, ptB ) )
110 {
111 reportTwoPointGeometry( aDrcItem, aMarkerPos, ptA, ptB, aLayer );
112 }
113 else
114 {
115 reportViolation( aDrcItem, aMarkerPos, aLayer );
116 }
117}
118
119
120void DRC_TEST_PROVIDER::reportTwoItemGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
121 const BOARD_ITEM* aItem1, const BOARD_ITEM* aItem2,
122 PCB_LAYER_ID aLayer, int aDistance )
123{
124 std::shared_ptr<SHAPE> aShape1 = aItem1->GetEffectiveShape( aLayer );
125 std::shared_ptr<SHAPE> aShape2 = aItem2->GetEffectiveShape( aLayer );
126
127 reportTwoShapeGeometry( aDrcItem, aMarkerPos, aShape1.get(), aShape2.get(), aLayer, aDistance );
128}
129
130
131bool DRC_TEST_PROVIDER::reportProgress( size_t aCount, size_t aSize, size_t aDelta )
132{
133 if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
134 {
135 if( !m_drcEngine->ReportProgress( static_cast<double>( aCount ) / aSize ) )
136 return false;
137 }
138
139 return true;
140}
141
142
143bool DRC_TEST_PROVIDER::reportPhase( const wxString& aMessage )
144{
145 REPORT_AUX( aMessage );
146 return m_drcEngine->ReportPhase( aMessage );
147}
148
149
150int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, const LSET& aLayers,
151 const std::function<bool( BOARD_ITEM*)>& aFunc )
152{
153 BOARD *brd = m_drcEngine->GetBoard();
154 std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
155 int n = 0;
156
157 if( aTypes.size() == 0 )
158 {
159 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
160 typeMask[ i ] = true;
161 }
162 else
163 {
164 for( KICAD_T aType : aTypes )
165 typeMask[ aType ] = true;
166 }
167
168 for( PCB_TRACK* item : brd->Tracks() )
169 {
170 if( (item->GetLayerSet() & aLayers).any() )
171 {
172 if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
173 {
174 aFunc( item );
175 n++;
176 }
177 else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
178 {
179 aFunc( item );
180 n++;
181 }
182 else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
183 {
184 aFunc( item );
185 n++;
186 }
187 }
188 }
189
190 for( BOARD_ITEM* item : brd->Drawings() )
191 {
192 if( (item->GetLayerSet() & aLayers).any() )
193 {
194 if( typeMask[ PCB_DIMENSION_T ] && BaseType( item->Type() ) == PCB_DIMENSION_T )
195 {
196 if( !aFunc( item ) )
197 return n;
198
199 n++;
200 }
201 else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T )
202 {
203 if( !aFunc( item ) )
204 return n;
205
206 n++;
207 }
208 else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
209 {
210 if( !aFunc( item ) )
211 return n;
212
213 n++;
214 }
215 else if( typeMask[ PCB_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T )
216 {
217 if( !aFunc( item ) )
218 return n;
219
220 n++;
221 }
222 else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
223 {
224 if( !aFunc( item ) )
225 return n;
226
227 n++;
228 }
229 else if( item->Type() == PCB_TABLE_T )
230 {
231 if( typeMask[ PCB_TABLE_T ] )
232 {
233 if( !aFunc( item ) )
234 return n;
235
236 n++;
237 }
238
239 if( typeMask[ PCB_TABLECELL_T ] )
240 {
241 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( item )->GetCells() )
242 {
243 if( !aFunc( cell ) )
244 return n;
245
246 n++;
247 }
248 }
249 }
250 else if( typeMask[ PCB_BARCODE_T ] && item->Type() == PCB_BARCODE_T )
251 {
252 if( !aFunc( item ) )
253 return n;
254
255 n++;
256 }
257 }
258 }
259
260 if( typeMask[ PCB_ZONE_T ] )
261 {
262 for( ZONE* item : brd->Zones() )
263 {
264 if( ( item->GetLayerSet() & aLayers ).any() )
265 {
266 if( !aFunc( item ) )
267 return n;
268
269 n++;
270 }
271 }
272 }
273
274 for( FOOTPRINT* footprint : brd->Footprints() )
275 {
276 if( typeMask[ PCB_FIELD_T ] )
277 {
278 for( PCB_FIELD* field : footprint->GetFields() )
279 {
280 if( ( field->GetLayerSet() & aLayers ).any() )
281 {
282 if( !aFunc( field ) )
283 return n;
284
285 n++;
286 }
287 }
288 }
289
290 if( typeMask[ PCB_PAD_T ] )
291 {
292 for( PAD* pad : footprint->Pads() )
293 {
294 // Careful: if a pad has a hole then it pierces all layers
295 if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
296 {
297 if( !aFunc( pad ) )
298 return n;
299
300 n++;
301 }
302 }
303 }
304
305 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
306 {
307 if( (dwg->GetLayerSet() & aLayers).any() )
308 {
309 if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T )
310 {
311 if( !aFunc( dwg ) )
312 return n;
313
314 n++;
315 }
316 else if( typeMask[ PCB_TEXT_T ] && dwg->Type() == PCB_TEXT_T )
317 {
318 if( !aFunc( dwg ) )
319 return n;
320
321 n++;
322 }
323 else if( typeMask[ PCB_TEXTBOX_T ] && dwg->Type() == PCB_TEXTBOX_T )
324 {
325 if( !aFunc( dwg ) )
326 return n;
327
328 n++;
329 }
330 else if( typeMask[ PCB_SHAPE_T ] && dwg->Type() == PCB_SHAPE_T )
331 {
332 if( !aFunc( dwg ) )
333 return n;
334
335 n++;
336 }
337 }
338 }
339
340 if( typeMask[ PCB_ZONE_T ] )
341 {
342 for( ZONE* zone : footprint->Zones() )
343 {
344 if( (zone->GetLayerSet() & aLayers).any() )
345 {
346 if( !aFunc( zone ) )
347 return n;
348
349 n++;
350 }
351 }
352 }
353
354 if( typeMask[ PCB_FOOTPRINT_T ] )
355 {
356 if( !aFunc( footprint ) )
357 return n;
358
359 n++;
360 }
361 }
362
363 return n;
364}
365
366
368{
369 if( const PCB_FIELD* field = dynamic_cast<const PCB_FIELD*>( aItem ) )
370 {
371 if( !field->IsVisible() )
372 return true;
373 }
374
375 return false;
376}
377
378
379wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
380 double aConstraint, double aActual, EDA_DATA_TYPE aType )
381{
382 wxString constraint_str = MessageTextFromValue( aConstraint, true, aType );
383 wxString actual_str = MessageTextFromValue( aActual, true, aType );
384
385 if( constraint_str == actual_str )
386 {
387 // Use more precise formatting if the message-text strings were equal.
388 constraint_str = StringFromValue( aConstraint, true, aType );
389 actual_str = StringFromValue( aActual, true, aType );
390 }
391
392 return wxString::Format( aFormatString, aSource, std::move( constraint_str ), std::move( actual_str ) );
393}
394
395wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
396 const EDA_ANGLE& aConstraint, const EDA_ANGLE& aActual )
397{
398 wxString constraint_str = MessageTextFromValue( aConstraint );
399 wxString actual_str = MessageTextFromValue( aActual );
400
401 if( constraint_str == actual_str )
402 {
403 // Use more precise formatting if the message-text strings were equal.
404 constraint_str = StringFromValue( aConstraint, true );
405 actual_str = StringFromValue( aActual, true );
406 }
407
408 return wxString::Format( aFormatString, aSource, std::move( constraint_str ), std::move( actual_str ) );
409}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:112
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:79
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
const ZONES & Zones() const
Definition board.h:367
const FOOTPRINTS & Footprints() const
Definition board.h:363
const TRACKS & Tracks() const
Definition board.h:361
const DRAWINGS & Drawings() const
Definition board.h:365
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...
static std::vector< KICAD_T > s_allBasicItemsButZones
virtual bool reportPhase(const wxString &aStageName)
void reportTwoShapeGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const SHAPE *aShape1, const SHAPE *aShape2, PCB_LAYER_ID aLayer, int aDistance)
int forEachGeometryItem(const std::vector< KICAD_T > &aTypes, const LSET &aLayers, const std::function< bool(BOARD_ITEM *)> &aFunc)
void reportTwoItemGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const BOARD_ITEM *aItem1, const BOARD_ITEM *aItem2, PCB_LAYER_ID aLayer, int aDistance)
void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, const std::function< void(PCB_MARKER *)> &aPathGenerator=[](PCB_MARKER *){})
void reportTwoPointGeometry(std::shared_ptr< DRC_ITEM > &aDrcItem, const VECTOR2I &aMarkerPos, const VECTOR2I &ptA, const VECTOR2I &ptB, PCB_LAYER_ID aLayer)
static std::vector< KICAD_T > s_allBasicItems
bool isInvisibleText(const BOARD_ITEM *aItem) const
virtual const wxString GetName() const
wxString formatMsg(const wxString &aFormatString, const wxString &aSource, double aConstraint, double aActual, EDA_DATA_TYPE aDataType=EDA_DATA_TYPE::DISTANCE)
virtual bool reportProgress(size_t aCount, size_t aSize, size_t aDelta=1)
void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:177
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:219
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Definition pad.h:54
void SetPath(const std::vector< PCB_SHAPE > &aShapes, const VECTOR2I &aStart, const VECTOR2I &aEnd)
Definition pcb_marker.h:155
An abstract shape on 2D plane.
Definition shape.h:126
bool NearestPoints(const SHAPE *aOther, VECTOR2I &aPtThis, VECTOR2I &aPtOther) const
Return the two points that mark the closest distance between this shape and aOther.
UNITS_PROVIDER(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits)
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:74
#define REPORT_AUX(s)
@ SEGMENT
Definition eda_shape.h:45
EDA_DATA_TYPE
The type of unit.
Definition eda_units.h:38
EDA_UNITS
Definition eda_units.h:48
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:254
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:242
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition typeinfo.h:111
@ 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:108
@ 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_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:107
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:95
@ 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_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:94
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:96
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695