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
51
52
59
60
62{
63 if( s_allBasicItems.size() == 0 )
64 {
65 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
66 {
67 if( i != PCB_FOOTPRINT_T && i != PCB_GROUP_T )
68 {
69 s_allBasicItems.push_back( (KICAD_T) i );
70
71 if( i != PCB_ZONE_T )
72 s_allBasicItemsButZones.push_back( (KICAD_T) i );
73 }
74 }
75 }
76}
77
78
79const wxString DRC_TEST_PROVIDER::GetName() const { return wxT( "<no name test>" ); }
80
81
82void DRC_TEST_PROVIDER::reportViolation( std::shared_ptr<DRC_ITEM>& item,
83 const VECTOR2I& aMarkerPos, int aMarkerLayer,
84 const std::function<void( PCB_MARKER* )>& aPathGenerator )
85{
86 item->SetViolatingTest( this );
87 m_drcEngine->ReportViolation( item, aMarkerPos, aMarkerLayer, aPathGenerator );
88}
89
90
91void DRC_TEST_PROVIDER::reportTwoPointGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
92 const VECTOR2I& ptA, const VECTOR2I& ptB, PCB_LAYER_ID aLayer )
93{
94 PCB_SHAPE ptAShape( nullptr, SHAPE_T::SEGMENT );
95 ptAShape.SetStart( ptA );
96 ptAShape.SetEnd( ptB );
97
98 reportViolation( aDrcItem, aMarkerPos, aLayer,
99 [&]( PCB_MARKER* aMarker )
100 {
101 aMarker->SetPath( { ptAShape }, ptA, ptB );
102 } );
103}
104
105
106void DRC_TEST_PROVIDER::reportTwoShapeGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
107 const SHAPE* aShape1, const SHAPE* aShape2, PCB_LAYER_ID aLayer,
108 int aDistance )
109{
110 VECTOR2I ptA, ptB;
111
112 if( aDistance == 0 )
113 {
114 reportTwoPointGeometry( aDrcItem, aMarkerPos, aMarkerPos, aMarkerPos, aLayer );
115 }
116 else if( aShape1->NearestPoints( aShape2, ptA, ptB ) )
117 {
118 reportTwoPointGeometry( aDrcItem, aMarkerPos, ptA, ptB, aLayer );
119 }
120 else
121 {
122 reportViolation( aDrcItem, aMarkerPos, aLayer );
123 }
124}
125
126
127void DRC_TEST_PROVIDER::reportTwoItemGeometry( std::shared_ptr<DRC_ITEM>& aDrcItem, const VECTOR2I& aMarkerPos,
128 const BOARD_ITEM* aItem1, const BOARD_ITEM* aItem2,
129 PCB_LAYER_ID aLayer, int aDistance )
130{
131 std::shared_ptr<SHAPE> aShape1 = aItem1->GetEffectiveShape( aLayer );
132 std::shared_ptr<SHAPE> aShape2 = aItem2->GetEffectiveShape( aLayer );
133
134 reportTwoShapeGeometry( aDrcItem, aMarkerPos, aShape1.get(), aShape2.get(), aLayer, aDistance );
135}
136
137
138bool DRC_TEST_PROVIDER::reportProgress( size_t aCount, size_t aSize, size_t aDelta )
139{
140 if( ( aCount % aDelta ) == 0 || aCount == aSize - 1 )
141 {
142 if( !m_drcEngine->ReportProgress( static_cast<double>( aCount ) / aSize ) )
143 return false;
144 }
145
146 return true;
147}
148
149
150bool DRC_TEST_PROVIDER::reportPhase( const wxString& aMessage )
151{
152 REPORT_AUX( aMessage );
153 return m_drcEngine->ReportPhase( aMessage );
154}
155
156
157int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes, const LSET& aLayers,
158 const std::function<bool( BOARD_ITEM*)>& aFunc )
159{
160 BOARD *brd = m_drcEngine->GetBoard();
161 std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
162 int n = 0;
163
164 if( aTypes.size() == 0 )
165 {
166 for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
167 typeMask[ i ] = true;
168 }
169 else
170 {
171 for( KICAD_T aType : aTypes )
172 typeMask[ aType ] = true;
173 }
174
175 for( PCB_TRACK* item : brd->Tracks() )
176 {
177 if( (item->GetLayerSet() & aLayers).any() )
178 {
179 if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
180 {
181 aFunc( item );
182 n++;
183 }
184 else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
185 {
186 aFunc( item );
187 n++;
188 }
189 else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
190 {
191 aFunc( item );
192 n++;
193 }
194 }
195 }
196
197 for( BOARD_ITEM* item : brd->Drawings() )
198 {
199 if( (item->GetLayerSet() & aLayers).any() )
200 {
201 if( typeMask[ PCB_DIMENSION_T ] && BaseType( item->Type() ) == PCB_DIMENSION_T )
202 {
203 if( !aFunc( item ) )
204 return n;
205
206 n++;
207 }
208 else if( typeMask[ PCB_SHAPE_T ] && item->Type() == PCB_SHAPE_T )
209 {
210 if( !aFunc( item ) )
211 return n;
212
213 n++;
214 }
215 else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
216 {
217 if( !aFunc( item ) )
218 return n;
219
220 n++;
221 }
222 else if( typeMask[ PCB_TEXTBOX_T ] && item->Type() == PCB_TEXTBOX_T )
223 {
224 if( !aFunc( item ) )
225 return n;
226
227 n++;
228 }
229 else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
230 {
231 if( !aFunc( item ) )
232 return n;
233
234 n++;
235 }
236 else if( item->Type() == PCB_TABLE_T )
237 {
238 if( typeMask[ PCB_TABLE_T ] )
239 {
240 if( !aFunc( item ) )
241 return n;
242
243 n++;
244 }
245
246 if( typeMask[ PCB_TABLECELL_T ] )
247 {
248 for( PCB_TABLECELL* cell : static_cast<PCB_TABLE*>( item )->GetCells() )
249 {
250 if( !aFunc( cell ) )
251 return n;
252
253 n++;
254 }
255 }
256 }
257 else if( typeMask[ PCB_BARCODE_T ] && item->Type() == PCB_BARCODE_T )
258 {
259 if( !aFunc( item ) )
260 return n;
261
262 n++;
263 }
264 }
265 }
266
267 if( typeMask[ PCB_ZONE_T ] )
268 {
269 for( ZONE* item : brd->Zones() )
270 {
271 if( ( item->GetLayerSet() & aLayers ).any() )
272 {
273 if( !aFunc( item ) )
274 return n;
275
276 n++;
277 }
278 }
279 }
280
281 for( FOOTPRINT* footprint : brd->Footprints() )
282 {
283 if( typeMask[ PCB_FIELD_T ] )
284 {
285 for( PCB_FIELD* field : footprint->GetFields() )
286 {
287 if( ( field->GetLayerSet() & aLayers ).any() )
288 {
289 if( !aFunc( field ) )
290 return n;
291
292 n++;
293 }
294 }
295 }
296
297 if( typeMask[ PCB_PAD_T ] )
298 {
299 for( PAD* pad : footprint->Pads() )
300 {
301 // Careful: if a pad has a hole then it pierces all layers
302 if( pad->HasHole() || ( pad->GetLayerSet() & aLayers ).any() )
303 {
304 if( !aFunc( pad ) )
305 return n;
306
307 n++;
308 }
309 }
310 }
311
312 for( BOARD_ITEM* dwg : footprint->GraphicalItems() )
313 {
314 if( (dwg->GetLayerSet() & aLayers).any() )
315 {
316 if( typeMask[ PCB_DIMENSION_T ] && BaseType( dwg->Type() ) == PCB_DIMENSION_T )
317 {
318 if( !aFunc( dwg ) )
319 return n;
320
321 n++;
322 }
323 else if( typeMask[ PCB_TEXT_T ] && dwg->Type() == PCB_TEXT_T )
324 {
325 if( !aFunc( dwg ) )
326 return n;
327
328 n++;
329 }
330 else if( typeMask[ PCB_TEXTBOX_T ] && dwg->Type() == PCB_TEXTBOX_T )
331 {
332 if( !aFunc( dwg ) )
333 return n;
334
335 n++;
336 }
337 else if( typeMask[ PCB_SHAPE_T ] && dwg->Type() == PCB_SHAPE_T )
338 {
339 if( !aFunc( dwg ) )
340 return n;
341
342 n++;
343 }
344 }
345 }
346
347 if( typeMask[ PCB_ZONE_T ] )
348 {
349 for( ZONE* zone : footprint->Zones() )
350 {
351 if( (zone->GetLayerSet() & aLayers).any() )
352 {
353 if( !aFunc( zone ) )
354 return n;
355
356 n++;
357 }
358 }
359 }
360
361 if( typeMask[ PCB_FOOTPRINT_T ] )
362 {
363 if( !aFunc( footprint ) )
364 return n;
365
366 n++;
367 }
368 }
369
370 return n;
371}
372
373
375{
376 if( const PCB_FIELD* field = dynamic_cast<const PCB_FIELD*>( aItem ) )
377 {
378 if( !field->IsVisible() )
379 return true;
380 }
381
382 return false;
383}
384
385
386wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
387 double aConstraint, double aActual, EDA_DATA_TYPE aType )
388{
389 wxString constraint_str = MessageTextFromValue( aConstraint, true, aType );
390 wxString actual_str = MessageTextFromValue( aActual, true, aType );
391
392 if( constraint_str == actual_str )
393 {
394 // Use more precise formatting if the message-text strings were equal.
395 constraint_str = StringFromValue( aConstraint, true, aType );
396 actual_str = StringFromValue( aActual, true, aType );
397 }
398
399 return wxString::Format( aFormatString, aSource, std::move( constraint_str ), std::move( actual_str ) );
400}
401
402wxString DRC_TEST_PROVIDER::formatMsg( const wxString& aFormatString, const wxString& aSource,
403 const EDA_ANGLE& aConstraint, const EDA_ANGLE& aActual )
404{
405 wxString constraint_str = MessageTextFromValue( aConstraint );
406 wxString actual_str = MessageTextFromValue( aActual );
407
408 if( constraint_str == actual_str )
409 {
410 // Use more precise formatting if the message-text strings were equal.
411 constraint_str = StringFromValue( aConstraint, true );
412 actual_str = StringFromValue( aActual, true );
413 }
414
415 return wxString::Format( aFormatString, aSource, std::move( constraint_str ), std::move( actual_str ) );
416}
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:83
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
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:178
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:220
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
Definition pad.h:55
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