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