KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_test_provider_connection_width.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.
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 3
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/gpl-3.0.html
19 * or you may search the http://www.gnu.org website for the version 3 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 <algorithm>
25#include <atomic>
26#include <deque>
27#include <optional>
28#include <utility>
29
30#include <wx/debug.h>
31
32#include <board.h>
35#include <drc/drc_item.h>
37#include <drc/drc_rtree.h>
39#include <footprint.h>
40#include <geometry/seg.h>
42#include <geometry/vertex_set.h>
43#include <math/box2.h>
44#include <math/vector2d.h>
45#include <pcb_shape.h>
46#include <progress_reporter.h>
47#include <thread_pool.h>
48#include <pcb_track.h>
49#include <pad.h>
50#include <zone.h>
51#include <advanced_config.h>
52
53/*
54 Checks for copper connections that are less than the specified minimum width
55
56 Errors generated:
57 - DRCE_CONNECTION_WIDTH
58*/
59
61{
64
65 bool operator==(const NETCODE_LAYER_CACHE_KEY& other) const
66 {
67 return Netcode == other.Netcode && Layer == other.Layer;
68 }
69};
70
71
72namespace std
73{
74 template <>
76 {
77 std::size_t operator()( const NETCODE_LAYER_CACHE_KEY& k ) const
78 {
79 constexpr std::size_t prime = 19937;
80
81 return hash<int>()( k.Netcode ) ^ ( hash<int>()( k.Layer ) * prime );
82 }
83 };
84}
85
86
88{
89public:
91 {}
92
94
95 virtual bool Run() override;
96
97 virtual const wxString GetName() const override { return wxT( "copper width" ); };
98
99private:
100 wxString layerDesc( PCB_LAYER_ID aLayer );
101};
102
103
105{
106public:
107 POLYGON_TEST( int aLimit ) :
108 VERTEX_SET( 0 ),
109 m_limit( aLimit )
110 {};
111
112 bool FindPairs( const SHAPE_LINE_CHAIN& aPoly )
113 {
114 m_hits.clear();
115 m_vertices.clear();
116 m_bbox = aPoly.BBox();
117
118 createList( aPoly );
119
120 m_vertices.front().updateList();
121
122 VERTEX* p = m_vertices.front().next;
123 std::set<VERTEX*> all_hits;
124
125 while( p != &m_vertices.front() )
126 {
127 VERTEX* match = nullptr;
128
129 // Only run the expensive search if we don't already have a match for the point
130 if( ( all_hits.empty() || all_hits.count( p ) == 0 ) && ( match = getKink( p ) ) != nullptr )
131 {
132 if( !all_hits.count( match ) && m_hits.emplace( p->i, match->i ).second )
133 {
134 all_hits.emplace( p );
135 all_hits.emplace( match );
136 all_hits.emplace( p->next );
137 all_hits.emplace( p->prev );
138 all_hits.emplace( match->next );
139 all_hits.emplace( match->prev );
140 }
141 }
142
143 p = p->next;
144 }
145
146 return !m_hits.empty();
147 }
148
149 std::set<std::pair<int, int>>& GetVertices()
150 {
151 return m_hits;
152 }
153
162 bool isSubstantial( const VERTEX* aA, const VERTEX* aB ) const
163 {
164 bool x_change = false;
165 bool y_change = false;
166
167 // This is a failsafe in case of invalid lists. Never check
168 // more than the total number of points in m_vertices
169 size_t checked = 0;
170 size_t total_pts = m_vertices.size();
171
172 const VERTEX* p0 = aA;
173 const VERTEX* p = getNextOutlineVertex( p0 );
174
175 while( !same_point( p, aB ) // We've reached the other inflection point
176 && !same_point( p, aA ) // We've gone around in a circle
177 && checked < total_pts // Fail-safe for invalid lists
178 && !( x_change && y_change ) ) // We've found a substantial change in both directions
179 {
180 double diff_x = std::abs( p->x - p0->x );
181 double diff_y = std::abs( p->y - p0->y );
182
183 // Check for a substantial change in the x or y direction
184 // This is measured by the set value of the minimum connection width
185 if( diff_x > m_limit )
186 x_change = true;
187
188 if( diff_y > m_limit )
189 y_change = true;
190
191 p = getNextOutlineVertex( p );
192
193 ++checked;
194 }
195
196 wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) );
197
198 if( !same_point( p, aA ) && ( !x_change || !y_change ) )
199 return false;
200
201 p = getPrevOutlineVertex( p0 );
202
203 x_change = false;
204 y_change = false;
205 checked = 0;
206
207 while( !same_point( p, aB ) // We've reached the other inflection point
208 && !same_point( p, aA ) // We've gone around in a circle
209 && checked < total_pts // Fail-safe for invalid lists
210 && !( x_change && y_change ) ) // We've found a substantial change in both directions
211 {
212 double diff_x = std::abs( p->x - p0->x );
213 double diff_y = std::abs( p->y - p0->y );
214
215 // Floating point zeros can have a negative sign, so we need to
216 // ensure that only substantive diversions count for a direction
217 // change
218 if( diff_x > m_limit )
219 x_change = true;
220
221 if( diff_y > m_limit )
222 y_change = true;
223
224 p = getPrevOutlineVertex( p );
225
226 ++checked;
227 }
228
229 wxCHECK_MSG( checked < total_pts, false, wxT( "Invalid polygon detected. Missing points to check" ) );
230
231 return ( same_point( p, aA ) || ( x_change && y_change ) );
232 }
233
234 VERTEX* getKink( VERTEX* aPt ) const
235 {
236 // The point needs to be at a concave surface
237 if( locallyInside( aPt->prev, aPt->next ) )
238 return nullptr;
239
240 // z-order range for the current point ± limit bounding box
241 const uint32_t maxZ = zOrder( aPt->x + m_limit, aPt->y + m_limit );
242 const uint32_t minZ = zOrder( aPt->x - m_limit, aPt->y - m_limit );
243 const SEG::ecoord limit2 = SEG::Square( m_limit );
244
245 // first look for points in increasing z-order
246 VERTEX* p = aPt->nextZ;
247 SEG::ecoord min_dist = std::numeric_limits<SEG::ecoord>::max();
248 VERTEX* retval = nullptr;
249
250 while( p && p->z <= maxZ )
251 {
252 int delta_i = std::abs( p->i - aPt->i );
253 VECTOR2D diff( p->x - aPt->x, p->y - aPt->y );
254 SEG::ecoord dist2 = diff.SquaredEuclideanNorm();
255
256 if( delta_i > 1 && dist2 < limit2 && dist2 < min_dist && dist2 > 0
257 && locallyInside( p, aPt ) && isSubstantial( p, aPt ) && isSubstantial( aPt, p ) )
258 {
259 min_dist = dist2;
260 retval = p;
261 }
262
263 p = p->nextZ;
264 }
265
266 p = aPt->prevZ;
267
268 while( p && p->z >= minZ )
269 {
270 int delta_i = std::abs( p->i - aPt->i );
271 VECTOR2D diff( p->x - aPt->x, p->y - aPt->y );
272 SEG::ecoord dist2 = diff.SquaredEuclideanNorm();
273
274 if( delta_i > 1 && dist2 < limit2 && dist2 < min_dist && dist2 > 0
275 && locallyInside( p, aPt ) && isSubstantial( p, aPt ) && isSubstantial( aPt, p ) )
276 {
277 min_dist = dist2;
278 retval = p;
279 }
280
281 p = p->prevZ;
282 }
283 return retval;
284 }
285
286private:
288 std::set<std::pair<int, int>> m_hits;
289};
290
291
293{
294 return wxString::Format( wxT( "(%s)" ), m_drcEngine->GetBoard()->GetLayerName( aLayer ) );
295}
296
297
299{
301 {
302 REPORT_AUX( wxT( "Connection width violations ignored. Tests not run." ) );
303 return true; // Continue with other tests
304 }
305
306 if( !reportPhase( _( "Checking nets for minimum connection width..." ) ) )
307 return false; // DRC cancelled
308
309 BOARD* board = m_drcEngine->GetBoard();
310 LSET copperLayerSet = board->GetEnabledLayers() & LSET::AllCuMask();
311 LSEQ copperLayers = copperLayerSet.Seq();
312 int epsilon = board->GetDesignSettings().GetDRCEpsilon();
313
314 // Zone knockouts can be approximated, and always have extra clearance built in
315 epsilon += board->GetDesignSettings().m_MaxError + pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_ExtraClearance );
316
317 // A neck in a zone fill can be between two knockouts. In this case it will be epsilon smaller
318 // on -each- side.
319 epsilon *= 2;
320
321 /*
322 * Build a set of distinct minWidths specified by various DRC rules. We'll run a test for
323 * each distinct minWidth, and then decide if any copper which failed that minWidth actually
324 * was required to abide by it or not.
325 */
326 std::set<int> distinctMinWidths = m_drcEngine->QueryDistinctConstraints( CONNECTION_WIDTH_CONSTRAINT );
327
328 if( m_drcEngine->IsCancelled() )
329 return false; // DRC cancelled
330
331 struct ITEMS_POLY
332 {
333 std::set<BOARD_ITEM*> Items;
334 SHAPE_POLY_SET Poly;
335 };
336
337 std::unordered_map<NETCODE_LAYER_CACHE_KEY, ITEMS_POLY> dataset;
338 std::atomic<size_t> done( 1 );
339
340 auto calc_effort =
341 [&]( const std::set<BOARD_ITEM*>& items, PCB_LAYER_ID aLayer ) -> size_t
342 {
343 size_t effort = 0;
344
345 for( BOARD_ITEM* item : items )
346 {
347 if( item->Type() == PCB_ZONE_T )
348 {
349 ZONE* zone = static_cast<ZONE*>( item );
350 effort += zone->GetFilledPolysList( aLayer )->FullPointCount();
351 }
352 else
353 {
354 effort += 4;
355 }
356 }
357
358 return effort;
359 };
360
361 /*
362 * For each net, on each layer, build a polygonSet which contains all the copper associated
363 * with that net on that layer.
364 */
365 auto build_netlayer_polys =
366 [&]( int aNetcode, const PCB_LAYER_ID aLayer ) -> size_t
367 {
368 if( m_drcEngine->IsCancelled() )
369 return 0;
370
371 ITEMS_POLY& itemsPoly = dataset[ { aNetcode, aLayer } ];
372
373 for( BOARD_ITEM* item : itemsPoly.Items )
374 item->TransformShapeToPolygon( itemsPoly.Poly, aLayer, 0, ARC_HIGH_DEF, ERROR_OUTSIDE );
375
376 itemsPoly.Poly.Fracture();
377
378 done.fetch_add( calc_effort( itemsPoly.Items, aLayer ) );
379
380 return 1;
381 };
382
383 /*
384 * Examine all necks in a given polygonSet which fail a given minWidth.
385 */
386 auto min_checker =
387 [&]( const ITEMS_POLY& aItemsPoly, const PCB_LAYER_ID aLayer, int aMinWidth ) -> size_t
388 {
389 if( m_drcEngine->IsCancelled() )
390 return 0;
391
392 int testWidth = aMinWidth - epsilon;
393
394 POLYGON_TEST test( testWidth );
395
396 for( int ii = 0; ii < aItemsPoly.Poly.OutlineCount(); ++ii )
397 {
398 const SHAPE_LINE_CHAIN& chain = aItemsPoly.Poly.COutline( ii );
399
400 test.FindPairs( chain );
401 auto& ret = test.GetVertices();
402
403 for( const std::pair<int, int>& pt : ret )
404 {
405 /*
406 * We've found a neck that fails the given aMinWidth. We now need to know
407 * if the objects the produced the copper at this location are required to
408 * abide by said aMinWidth or not. (If so, we have a violation.)
409 *
410 * We find the contributingItems by hit-testing at the choke point (the
411 * centre point of the neck), and then run the rules engine on those
412 * contributingItems. If the reported constraint matches aMinWidth, then
413 * we've got a violation.
414 */
415 SEG span( chain.CPoint( pt.first ), chain.CPoint( pt.second ) );
416 VECTOR2I location = ( span.A + span.B ) / 2;
417 int dist = ( span.A - span.B ).EuclideanNorm();
418
419 std::vector<BOARD_ITEM*> contributingItems;
420
421 for( auto* item : board->m_CopperItemRTreeCache->GetObjectsAt( location,
422 aLayer,
423 aMinWidth ) )
424 {
425 if( item->HitTest( location, aMinWidth ) )
426 contributingItems.push_back( item );
427 }
428
429 for( auto& [ zone, rtree ] : board->m_CopperZoneRTreeCache )
430 {
431 if( !rtree.get() )
432 continue;
433
434 auto obj_list = rtree->GetObjectsAt( location, aLayer, aMinWidth );
435
436 if( !obj_list.empty() && zone->HitTestFilledArea( aLayer, location, aMinWidth ) )
437 contributingItems.push_back( zone );
438 }
439
440 if( !contributingItems.empty() )
441 {
442 BOARD_ITEM* item1 = contributingItems[0];
443 BOARD_ITEM* item2 = contributingItems.size() > 1 ? contributingItems[1]
444 : nullptr;
446 item1, item2, aLayer );
447
448 if( c.Value().Min() == aMinWidth )
449 {
451 wxString msg;
452
453 msg = formatMsg( _( "(%s minimum connection width %s; actual %s)" ),
454 c.GetName(),
455 c.Value().Min(),
456 dist );
457
458 msg += wxS( " " ) + layerDesc( aLayer );
459
460 drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + msg );
461 drce->SetViolatingRule( c.GetParentRule() );
462
463 for( BOARD_ITEM* item : contributingItems )
464 drce->AddItem( item );
465
466 reportViolation( drce, location, aLayer );
467 }
468 }
469 }
470 }
471
472 done.fetch_add( calc_effort( aItemsPoly.Items, aLayer ) );
473
474 return 1;
475 };
476
477 for( PCB_LAYER_ID layer : copperLayers )
478 {
479 for( ZONE* zone : board->m_DRCCopperZones )
480 {
481 if( !zone->GetIsRuleArea() && zone->IsOnLayer( layer ) )
482 dataset[ { zone->GetNetCode(), layer } ].Items.emplace( zone );
483 }
484
485 for( PCB_TRACK* track : board->Tracks() )
486 {
487 if( PCB_VIA* via = dynamic_cast<PCB_VIA*>( track ) )
488 {
489 if( via->FlashLayer( static_cast<int>( layer ) ) )
490 dataset[ { via->GetNetCode(), layer } ].Items.emplace( via );
491 }
492 else if( track->IsOnLayer( layer ) )
493 {
494 dataset[ { track->GetNetCode(), layer } ].Items.emplace( track );
495 }
496 }
497
498 for( FOOTPRINT* fp : board->Footprints() )
499 {
500 for( PAD* pad : fp->Pads() )
501 {
502 if( pad->FlashLayer( static_cast<int>( layer ) ) )
503 dataset[ { pad->GetNetCode(), layer } ].Items.emplace( pad );
504 }
505
506 // Footprint zones are also in the m_DRCCopperZones cache
507 }
508 }
509
511 std::vector<std::future<size_t>> returns;
512 size_t total_effort = 0;
513
514 for( const auto& [ netLayer, itemsPoly ] : dataset )
515 total_effort += calc_effort( itemsPoly.Items, netLayer.Layer );
516
517 total_effort += std::max( (size_t) 1, total_effort ) * distinctMinWidths.size();
518
519 returns.reserve( dataset.size() );
520
521 for( const auto& [ netLayer, itemsPoly ] : dataset )
522 {
523 returns.emplace_back( tp.submit( build_netlayer_polys, netLayer.Netcode, netLayer.Layer ) );
524 }
525
526 for( std::future<size_t>& ret : returns )
527 {
528 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
529
530 while( status != std::future_status::ready )
531 {
532 reportProgress( done, total_effort );
533 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
534 }
535 }
536
537 returns.clear();
538 returns.reserve( dataset.size() * distinctMinWidths.size() );
539
540 for( const auto& [ netLayer, itemsPoly ] : dataset )
541 {
542 for( int minWidth : distinctMinWidths )
543 {
544 if( minWidth - epsilon <= 0 )
545 continue;
546
547 returns.emplace_back( tp.submit( min_checker, itemsPoly, netLayer.Layer, minWidth ) );
548 }
549 }
550
551 for( std::future<size_t>& ret : returns )
552 {
553 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
554
555 while( status != std::future_status::ready )
556 {
557 reportProgress( done, total_effort );
558 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
559 }
560 }
561
562 return true;
563}
564
565
566namespace detail
567{
569}
@ ERROR_OUTSIDE
Definition: approximation.h:33
constexpr int ARC_HIGH_DEF
Definition: base_units.h:129
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
int GetDRCEpsilon() const
Return an epsilon which accounts for rounding errors, etc.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
Definition: board_item.cpp:291
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:314
std::vector< ZONE * > m_DRCCopperZones
Definition: board.h:1348
const FOOTPRINTS & Footprints() const
Definition: board.h:355
const TRACKS & Tracks() const
Definition: board.h:353
std::shared_ptr< DRC_RTREE > m_CopperItemRTreeCache
Definition: board.h:1342
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:611
std::unordered_map< ZONE *, std::unique_ptr< DRC_RTREE > > m_CopperZoneRTreeCache
Definition: board.h:1341
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:943
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
Definition: board.cpp:826
wxString GetName() const
Definition: drc_rule.h:168
MINOPTMAX< int > & Value()
Definition: drc_rule.h:161
DRC_RULE * GetParentRule() const
Definition: drc_rule.h:164
BOARD * GetBoard() const
Definition: drc_engine.h:95
std::set< int > QueryDistinctConstraints(DRC_CONSTRAINT_T aConstraintId)
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:693
bool IsCancelled() const
static std::shared_ptr< DRC_ITEM > Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
Definition: drc_item.cpp:393
virtual ~DRC_TEST_PROVIDER_CONNECTION_WIDTH()=default
virtual const wxString GetName() const override
virtual bool Run() override
Run this provider against the given PCB with configured options (if any).
Represent a DRC "provider" which runs some DRC functions over a BOARD and spits out DRC_ITEM and posi...
virtual bool reportPhase(const wxString &aStageName)
virtual void reportViolation(std::shared_ptr< DRC_ITEM > &item, const VECTOR2I &aMarkerPos, int aMarkerLayer, DRC_CUSTOM_MARKER_HANDLER *aCustomHandler=nullptr)
DRC_ENGINE * m_drcEngine
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)
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
Definition: lseq.h:47
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:37
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:583
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:297
T Min() const
Definition: minoptmax.h:33
Definition: pad.h:54
bool isSubstantial(const VERTEX *aA, const VERTEX *aB) const
Checks to see if there is a "substantial" protrusion in each polygon produced by the cut from aA to a...
VERTEX * getKink(VERTEX *aPt) const
bool FindPairs(const SHAPE_LINE_CHAIN &aPoly)
std::set< std::pair< int, int > > & GetVertices()
std::set< std::pair< int, int > > m_hits
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I::extended_type ecoord
Definition: seg.h:44
VECTOR2I B
Definition: seg.h:50
static SEG::ecoord Square(int a)
Definition: seg.h:123
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a set of closed polygons.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:307
std::deque< VERTEX > m_vertices
Definition: vertex_set.h:343
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
Definition: vertex_set.cpp:27
bool locallyInside(const VERTEX *a, const VERTEX *b) const
Check whether the segment from vertex a -> vertex b is inside the polygon around the immediate area o...
Definition: vertex_set.cpp:173
BOX2I m_bbox
Definition: vertex_set.h:342
VERTEX * getPrevOutlineVertex(const VERTEX *aPt) const
Get the previous vertex in the outline, avoiding steiner points and points that overlap with splits.
Definition: vertex_set.cpp:144
VERTEX * getNextOutlineVertex(const VERTEX *aPt) const
Get the next vertex in the outline, avoiding steiner points and points that overlap with splits.
Definition: vertex_set.cpp:117
uint32_t zOrder(const double aX, const double aY) const
Note that while the inputs are doubles, these are scaled by the size of the bounding box to fit into ...
Definition: vertex_set.cpp:81
bool same_point(const VERTEX *aA, const VERTEX *aB) const
Check if two vertices are at the same point.
Definition: vertex_set.cpp:112
const double x
Definition: vertex_set.h:235
VERTEX * next
Definition: vertex_set.h:241
VERTEX * prevZ
Definition: vertex_set.h:247
VERTEX * nextZ
Definition: vertex_set.h:248
VERTEX * prev
Definition: vertex_set.h:240
const int i
Definition: vertex_set.h:234
uint32_t z
Definition: vertex_set.h:244
const double y
Definition: vertex_set.h:236
Handle a list of polygons defining a copper zone.
Definition: zone.h:74
bool GetIsRuleArea() const
Accessors to parameters used in Rule Area zones:
Definition: zone.h:699
const std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:595
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Test to see if this object is on the given layer.
Definition: zone.cpp:616
@ DRCE_CONNECTION_WIDTH
Definition: drc_item.h:59
@ CONNECTION_WIDTH_CONSTRAINT
Definition: drc_rule.h:80
#define REPORT_AUX(s)
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
static DRC_REGISTER_TEST_PROVIDER< DRC_TEST_PROVIDER_ANNULAR_WIDTH > dummy
STL namespace.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:393
const double epsilon
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
bool operator==(const NETCODE_LAYER_CACHE_KEY &other) const
std::size_t operator()(const NETCODE_LAYER_CACHE_KEY &k) const
const SHAPE_LINE_CHAIN chain
VECTOR2I location
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
Definition: thread_pool.cpp:30
static thread_pool * tp
Definition: thread_pool.cpp:28
BS::thread_pool thread_pool
Definition: thread_pool.h:31
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107