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