KiCad PCB EDA Suite
drc.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 (C) 2004-2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
6  * Copyright (C) 2017-2019 KiCad Developers, see change_log.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
30 #include <fctsys.h>
31 #include <pcb_edit_frame.h>
32 #include <trigo.h>
33 #include <board_design_settings.h>
34 #include <class_edge_mod.h>
35 #include <class_drawsegment.h>
36 #include <class_module.h>
37 #include <class_track.h>
38 #include <class_pad.h>
39 #include <class_zone.h>
40 #include <class_pcb_text.h>
41 #include <class_draw_panel_gal.h>
42 #include <view/view.h>
43 #include <geometry/seg.h>
44 #include <math_for_graphics.h>
48 
49 #include <tool/tool_manager.h>
50 #include <tools/pcb_actions.h>
51 
52 #include <kiface_i.h>
53 #include <pcbnew.h>
54 #include <drc.h>
55 #include <pcb_netlist.h>
56 
57 #include <dialog_drc.h>
58 #include <wx/progdlg.h>
59 #include <board_commit.h>
60 #include <geometry/shape_segment.h>
61 #include <geometry/shape_arc.h>
62 
63 #include <drc/courtyard_overlap.h>
64 
65 void DRC::ShowDRCDialog( wxWindow* aParent )
66 {
67  bool show_dlg_modal = true;
68 
69  // the dialog needs a parent frame. if it is not specified, this is
70  // the PCB editor frame specified in DRC class.
71  if( aParent == NULL )
72  {
73  // if any parent is specified, the dialog is modal.
74  // if this is the default PCB editor frame, it is not modal
75  show_dlg_modal = false;
76  aParent = m_pcbEditorFrame;
77  }
78 
80  toolMgr->RunAction( ACTIONS::cancelInteractive, true );
81  toolMgr->DeactivateTool();
82  toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
83 
84  if( !m_drcDialog )
85  {
86  m_drcDialog = new DIALOG_DRC_CONTROL( this, m_pcbEditorFrame, aParent );
88 
90 
91  if( show_dlg_modal )
92  m_drcDialog->ShowModal();
93  else
94  m_drcDialog->Show( true );
95  }
96  else // The dialog is just not visible (because the user has double clicked on an error item)
97  {
99  m_drcDialog->Show( true );
100  }
101 }
102 
103 
105 {
106  // In legacy routing mode, do not add markers to the board.
107  // only shows the drc error message
109  {
110  m_pcbEditorFrame->SetMsgPanel( aMarker );
111  delete aMarker;
112  m_currentMarker = nullptr;
113  }
114  else
115  {
116  BOARD_COMMIT commit( m_pcbEditorFrame );
117  commit.Add( aMarker );
118  commit.Push( wxEmptyString, false, false );
119  }
120 }
121 
122 
123 void DRC::DestroyDRCDialog( int aReason )
124 {
125  if( m_drcDialog )
126  {
128 
129  m_drcDialog->Destroy();
130  m_drcDialog = NULL;
131  }
132 }
133 
134 
135 DRC::DRC( PCB_EDIT_FRAME* aPcbWindow )
136 {
137  m_pcbEditorFrame = aPcbWindow;
138  m_pcb = aPcbWindow->GetBoard();
139  m_drcDialog = NULL;
140 
141  // establish initial values for everything:
142  m_drcInLegacyRoutingMode = false;
143  m_doPad2PadTest = true; // enable pad to pad clearance tests
144  m_doUnconnectedTest = true; // enable unconnected tests
145  m_doZonesTest = false; // disable zone to items clearance tests
146  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
147  m_refillZones = false; // Only fill zones if requested by user.
148  m_reportAllTrackErrors = false;
149  m_testFootprints = false;
150 
151  m_drcRun = false;
152  m_footprintsTested = false;
153 
154  m_doCreateRptFile = false;
155  // m_rptFilename set to empty by its constructor
156 
157  m_currentMarker = NULL;
158 
159  m_segmAngle = 0;
160  m_segmLength = 0;
161 
162  m_xcliplo = 0;
163  m_ycliplo = 0;
164  m_xcliphi = 0;
165  m_ycliphi = 0;
166 
167  m_markerFactory.SetUnitsProvider( [=]() { return aPcbWindow->GetUserUnits(); } );
168 }
169 
170 
172 {
173  for( DRC_ITEM* unconnectedItem : m_unconnected )
174  delete unconnectedItem;
175 
176  for( DRC_ITEM* footprintItem : m_footprints )
177  delete footprintItem;
178 }
179 
180 
181 int DRC::DrcOnCreatingTrack( TRACK* aRefSegm, TRACK* aList )
182 {
183  updatePointers();
184 
185  // Set right options for this on line drc
186  int drc_state = m_drcInLegacyRoutingMode;
188  int rpt_state = m_reportAllTrackErrors;
189  m_reportAllTrackErrors = false;
190 
191  // Test new segment against tracks and pads, not against copper zones
192  if( !doTrackDrc( aRefSegm, aList, true, false ) )
193  {
194  if( m_currentMarker )
195  {
197  delete m_currentMarker;
198  m_currentMarker = nullptr;
199  }
200 
201  m_drcInLegacyRoutingMode = drc_state;
202  m_reportAllTrackErrors = rpt_state;
203  return BAD_DRC;
204  }
205 
206  if( !doTrackKeepoutDrc( aRefSegm ) )
207  {
208  if( m_currentMarker )
209  {
211  delete m_currentMarker;
212  m_currentMarker = nullptr;
213  }
214 
215  m_drcInLegacyRoutingMode = drc_state;
216  m_reportAllTrackErrors = rpt_state;
217  return BAD_DRC;
218  }
219 
220  m_drcInLegacyRoutingMode = drc_state;
221  m_reportAllTrackErrors = rpt_state;
222  return OK_DRC;
223 }
224 
225 
226 int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
227 {
228  BOARD* board = m_pcbEditorFrame->GetBoard();
229  BOARD_COMMIT commit( m_pcbEditorFrame );
230  int nerrors = 0;
231 
232  std::vector<SHAPE_POLY_SET> smoothed_polys;
233  smoothed_polys.resize( board->GetAreaCount() );
234 
235  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
236  {
237  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
238  zoneRef->BuildSmoothedPoly( smoothed_polys[ia] );
239  }
240 
241  // iterate through all areas
242  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
243  {
244  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
245 
246  if( !zoneRef->IsOnCopperLayer() )
247  continue;
248 
249  // When testing only a single area, skip all others
250  if( aZone && ( aZone != zoneRef) )
251  continue;
252 
253  // If we are testing a single zone, then iterate through all other zones
254  // Otherwise, we have already tested the zone combination
255  for( int ia2 = ( aZone ? 0 : ia + 1 ); ia2 < board->GetAreaCount(); ia2++ )
256  {
257  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
258 
259  if( zoneRef == zoneToTest )
260  continue;
261 
262  // test for same layer
263  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
264  continue;
265 
266  // Test for same net
267  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
268  continue;
269 
270  // test for different priorities
271  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
272  continue;
273 
274  // test for different types
275  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
276  continue;
277 
278  // Examine a candidate zone: compare zoneToTest to zoneRef
279 
280  // Get clearance used in zone to zone test. The policy used to
281  // obtain that value is now part of the zone object itself by way of
282  // ZONE_CONTAINER::GetClearance().
283  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
284 
285  // Keepout areas have no clearance, so set zone2zoneClearance to 1
286  // ( zone2zoneClearance = 0 can create problems in test functions)
287  if( zoneRef->GetIsKeepout() )
288  zone2zoneClearance = 1;
289 
290  // test for some corners of zoneRef inside zoneToTest
291  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
292  {
293  VECTOR2I currentVertex = *iterator;
294  wxPoint pt( currentVertex.x, currentVertex.y );
295 
296  if( smoothed_polys[ia2].Contains( currentVertex ) )
297  {
298  if( aCreateMarkers )
299  commit.Add( m_markerFactory.NewMarker(
300  pt, zoneRef, zoneToTest, DRCE_ZONES_INTERSECT ) );
301 
302  nerrors++;
303  }
304  }
305 
306  // test for some corners of zoneToTest inside zoneRef
307  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
308  {
309  VECTOR2I currentVertex = *iterator;
310  wxPoint pt( currentVertex.x, currentVertex.y );
311 
312  if( smoothed_polys[ia].Contains( currentVertex ) )
313  {
314  if( aCreateMarkers )
315  commit.Add( m_markerFactory.NewMarker(
316  pt, zoneToTest, zoneRef, DRCE_ZONES_INTERSECT ) );
317 
318  nerrors++;
319  }
320  }
321 
322  // Iterate through all the segments of refSmoothedPoly
323  std::set<wxPoint> conflictPoints;
324 
325  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
326  {
327  // Build ref segment
328  SEG refSegment = *refIt;
329 
330  // Iterate through all the segments in smoothed_polys[ia2]
331  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
332  {
333  // Build test segment
334  SEG testSegment = *testIt;
335  wxPoint pt;
336 
337  int ax1, ay1, ax2, ay2;
338  ax1 = refSegment.A.x;
339  ay1 = refSegment.A.y;
340  ax2 = refSegment.B.x;
341  ay2 = refSegment.B.y;
342 
343  int bx1, by1, bx2, by2;
344  bx1 = testSegment.A.x;
345  by1 = testSegment.A.y;
346  bx2 = testSegment.B.x;
347  by2 = testSegment.B.y;
348 
349  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
350  0,
351  ax1, ay1, ax2, ay2,
352  0,
353  zone2zoneClearance,
354  &pt.x, &pt.y );
355 
356  if( d < zone2zoneClearance )
357  conflictPoints.insert( pt );
358  }
359  }
360 
361  for( wxPoint pt : conflictPoints )
362  {
363  if( aCreateMarkers )
364  commit.Add( m_markerFactory.NewMarker(
365  pt, zoneRef, zoneToTest, DRCE_ZONES_TOO_CLOSE ) );
366 
367  nerrors++;
368  }
369  }
370  }
371 
372  if( aCreateMarkers )
373  commit.Push( wxEmptyString, false, false );
374 
375  return nerrors;
376 }
377 
378 
379 int DRC::DrcOnCreatingZone( ZONE_CONTAINER* aArea, int aCornerIndex )
380 {
381  updatePointers();
382 
383  // Set right options for this on line drc
384  int drc_state = m_drcInLegacyRoutingMode;
386  int rpt_state = m_reportAllTrackErrors;
387  m_reportAllTrackErrors = false;
388 
389  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
390  {
391  wxASSERT( m_currentMarker );
393  delete m_currentMarker;
394  m_currentMarker = nullptr;
395  m_drcInLegacyRoutingMode = drc_state;
396  m_reportAllTrackErrors = rpt_state;
397  return BAD_DRC;
398  }
399 
400  m_drcInLegacyRoutingMode = drc_state;
401  m_reportAllTrackErrors = rpt_state;
402  return OK_DRC;
403 }
404 
405 
406 void DRC::RunTests( wxTextCtrl* aMessages )
407 {
408  // be sure m_pcb is the current board, not a old one
409  // ( the board can be reloaded )
411 
412  if( aMessages )
413  {
414  aMessages->AppendText( _( "Board Outline...\n" ) );
415  wxSafeYield();
416  }
417 
418  testOutline();
419 
420  // someone should have cleared the two lists before calling this.
421  if( !testNetClasses() )
422  {
423  // testing the netclasses is a special case because if the netclasses
424  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
425  // class (a NET) will cause its items such as tracks, vias, and pads
426  // to also fail. So quit after *all* netclass errors have been reported.
427  if( aMessages )
428  aMessages->AppendText( _( "Aborting\n" ) );
429 
430  // update the m_drcDialog listboxes
431  updatePointers();
432 
433  return;
434  }
435 
436  // test pad to pad clearances, nothing to do with tracks, vias or zones.
437  if( m_doPad2PadTest )
438  {
439  if( aMessages )
440  {
441  aMessages->AppendText( _( "Pad clearances...\n" ) );
442  wxSafeYield();
443  }
444 
445  testPad2Pad();
446  }
447 
448  // test clearances between drilled holes
449  if( aMessages )
450  {
451  aMessages->AppendText( _( "Drill clearances...\n" ) );
452  wxSafeYield();
453  }
454 
456 
457  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
458  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
459 
460  if( m_refillZones )
461  {
462  if( aMessages )
463  aMessages->AppendText( _( "Refilling all zones...\n" ) );
464 
466  }
467  else
468  {
469  if( aMessages )
470  aMessages->AppendText( _( "Checking zone fills...\n" ) );
471 
473  }
474 
475  // test track and via clearances to other tracks, pads, and vias
476  if( aMessages )
477  {
478  aMessages->AppendText( _( "Track clearances...\n" ) );
479  wxSafeYield();
480  }
481 
482  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
483 
484  // test zone clearances to other zones
485  if( aMessages )
486  {
487  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
488  wxSafeYield();
489  }
490 
491  testZones();
492 
493  // find and gather unconnected pads.
494  if( m_doUnconnectedTest )
495  {
496  if( aMessages )
497  {
498  aMessages->AppendText( _( "Unconnected pads...\n" ) );
499  aMessages->Refresh();
500  }
501 
502  testUnconnected();
503  }
504 
505  // find and gather vias, tracks, pads inside keepout areas.
506  if( m_doKeepoutTest )
507  {
508  if( aMessages )
509  {
510  aMessages->AppendText( _( "Keepout areas ...\n" ) );
511  aMessages->Refresh();
512  }
513 
515  }
516 
517  // find and gather vias, tracks, pads inside text boxes.
518  if( aMessages )
519  {
520  aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
521  wxSafeYield();
522  }
523 
525 
526  // find overlapping courtyard ares.
529  {
530  if( aMessages )
531  {
532  aMessages->AppendText( _( "Courtyard areas...\n" ) );
533  aMessages->Refresh();
534  }
535 
537  }
538 
539  for( DRC_ITEM* footprintItem : m_footprints )
540  delete footprintItem;
541 
542  m_footprints.clear();
543  m_footprintsTested = false;
544 
545  if( m_testFootprints && !Kiface().IsSingle() )
546  {
547  if( aMessages )
548  {
549  aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
550  aMessages->Refresh();
551  }
552 
553  NETLIST netlist;
555 
556  if( m_drcDialog )
557  m_drcDialog->Raise();
558 
560  m_footprintsTested = true;
561  }
562 
563  // Check if there are items on disabled layers
565 
566  if( aMessages )
567  {
568  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
569  aMessages->Refresh();
570  }
571 
572  m_drcRun = true;
573 
574  // update the m_drcDialog listboxes
575  updatePointers();
576 
577  if( aMessages )
578  {
579  // no newline on this one because it is last, don't want the window
580  // to unnecessarily scroll.
581  aMessages->AppendText( _( "Finished" ) );
582  }
583 }
584 
585 
587 {
588  // update my pointers, m_pcbEditorFrame is the only unchangeable one
590 
591  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
592  {
599 
601  }
602 }
603 
604 
605 bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
606 {
607  bool ret = true;
608 
610 
611 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
612 
613 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
614  if( nc->GetClearance() < g.m_MinClearance )
615  {
616  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
617  GetChars( nc->GetName() ),
618  FmtVal( nc->GetClearance() ),
619  FmtVal( g.m_TrackClearance )
620  );
621 
623  m_currentMarker = nullptr;
624  ret = false;
625  }
626 #endif
627 
628  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
629  {
630  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
631  GetChars( nc->GetName() ),
632  FmtVal( nc->GetTrackWidth() ),
634  );
635 
637  ret = false;
638  }
639 
640  if( nc->GetViaDiameter() < g.m_ViasMinSize )
641  {
642  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
643  GetChars( nc->GetName() ),
644  FmtVal( nc->GetViaDiameter() ),
645  FmtVal( g.m_ViasMinSize )
646  );
647 
649  ret = false;
650  }
651 
652  if( nc->GetViaDrill() < g.m_ViasMinDrill )
653  {
654  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
655  GetChars( nc->GetName() ),
656  FmtVal( nc->GetViaDrill() ),
658  );
659 
661  ret = false;
662  }
663 
664  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
665  {
666  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
667  GetChars( nc->GetName() ),
668  FmtVal( nc->GetuViaDiameter() ),
669  FmtVal( g.m_MicroViasMinSize ) );
670 
672  ret = false;
673  }
674 
675  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
676  {
677  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
678  GetChars( nc->GetName() ),
679  FmtVal( nc->GetuViaDrill() ),
681 
683  ret = false;
684  }
685 
686  return ret;
687 }
688 
689 
691 {
692  bool ret = true;
693 
695 
696  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
697 
698  if( !doNetClass( netclasses.GetDefault(), msg ) )
699  ret = false;
700 
701  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
702  {
703  NETCLASSPTR nc = i->second;
704 
705  if( !doNetClass( nc, msg ) )
706  ret = false;
707  }
708 
709  return ret;
710 }
711 
712 
714 {
715  std::vector<D_PAD*> sortedPads;
716 
717  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
718 
719  if( sortedPads.size() == 0 )
720  return;
721 
722  // find the max size of the pads (used to stop the test)
723  int max_size = 0;
724 
725  for( unsigned i = 0; i < sortedPads.size(); ++i )
726  {
727  D_PAD* pad = sortedPads[i];
728 
729  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
730  int radius = pad->GetBoundingRadius();
731 
732  if( radius > max_size )
733  max_size = radius;
734  }
735 
736  // Upper limit of pad list (limit not included)
737  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
738 
739  // Test the pads
740  for( unsigned i = 0; i< sortedPads.size(); ++i )
741  {
742  D_PAD* pad = sortedPads[i];
743 
744  int x_limit = max_size + pad->GetClearance() +
745  pad->GetBoundingRadius() + pad->GetPosition().x;
746 
747  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
748  {
749  wxASSERT( m_currentMarker );
751  m_currentMarker = nullptr;
752  }
753  }
754 }
755 
756 
758 {
759  int holeToHoleMin = m_pcb->GetDesignSettings().m_HoleToHoleMin;
760 
761  if( holeToHoleMin == 0 ) // No min setting turns testing off.
762  return;
763 
764  // Test drilled hole clearances to minimize drill bit breakage.
765  //
766  // Notes: slots are milled, so we're only concerned with circular holes
767  // microvias are laser-drilled, so we're only concerned with standard vias
768 
769  struct DRILLED_HOLE
770  {
771  wxPoint m_location;
772  int m_drillRadius;
773  BOARD_ITEM* m_owner;
774  };
775 
776  std::vector<DRILLED_HOLE> holes;
777  DRILLED_HOLE hole;
778 
779  for( MODULE* mod : m_pcb->Modules() )
780  {
781  for( D_PAD* pad : mod->Pads( ) )
782  {
783  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
784  {
785  hole.m_location = pad->GetPosition();
786  hole.m_drillRadius = pad->GetDrillSize().x / 2;
787  hole.m_owner = pad;
788  holes.push_back( hole );
789  }
790  }
791  }
792 
793  for( TRACK* track : m_pcb->Tracks() )
794  {
795  VIA* via = dynamic_cast<VIA*>( track );
796  if( via && via->GetViaType() == VIA_THROUGH )
797  {
798  hole.m_location = via->GetPosition();
799  hole.m_drillRadius = via->GetDrillValue() / 2;
800  hole.m_owner = via;
801  holes.push_back( hole );
802  }
803  }
804 
805  for( size_t ii = 0; ii < holes.size(); ++ii )
806  {
807  const DRILLED_HOLE& refHole = holes[ ii ];
808 
809  for( size_t jj = ii + 1; jj < holes.size(); ++jj )
810  {
811  const DRILLED_HOLE& checkHole = holes[ jj ];
812 
813  // Holes with identical locations are allowable
814  if( checkHole.m_location == refHole.m_location )
815  continue;
816 
817  if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
818  < checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
819  {
821  DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
822  refHole.m_owner, refHole.m_location,
823  checkHole.m_owner, checkHole.m_location ) );
824  }
825  }
826  }
827 }
828 
829 
830 void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar )
831 {
832  wxProgressDialog * progressDialog = NULL;
833  const int delta = 500; // This is the number of tests between 2 calls to the
834  // progress bar
835  int count = 0;
836 
837  for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
838  count++;
839 
840  int deltamax = count/delta;
841 
842  if( aShowProgressBar && deltamax > 3 )
843  {
844  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
845  // on OSX
846  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
847  deltamax, aActiveWindow,
848  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
849  progressDialog->Update( 0, wxEmptyString );
850  }
851 
852  int ii = 0;
853  count = 0;
854 
855  for( TRACK* segm = m_pcb->m_Track; segm; segm = segm->Next() )
856  {
857  if( ii++ > delta )
858  {
859  ii = 0;
860  count++;
861 
862  if( progressDialog )
863  {
864  if( !progressDialog->Update( count, wxEmptyString ) )
865  break; // Aborted by user
866 #ifdef __WXMAC__
867  // Work around a dialog z-order issue on OS X
868  if( count == deltamax )
869  aActiveWindow->Raise();
870 #endif
871  }
872  }
873 
874  // Test new segment against tracks and pads, optionally against copper zones
875  if( !doTrackDrc( segm, segm->Next(), true, m_doZonesTest ) )
876  {
877  if( m_currentMarker )
878  {
880  m_currentMarker = nullptr;
881  }
882  }
883  }
884 
885  if( progressDialog )
886  progressDialog->Destroy();
887 }
888 
889 
891 {
892  for( DRC_ITEM* unconnectedItem : m_unconnected )
893  delete unconnectedItem;
894 
895  m_unconnected.clear();
896 
897  auto connectivity = m_pcb->GetConnectivity();
898 
899  connectivity->Clear();
900  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
901  connectivity->RecalculateRatsnest();
902 
903  std::vector<CN_EDGE> edges;
904  connectivity->GetUnconnectedEdges( edges );
905 
906  for( const auto& edge : edges )
907  {
908  auto src = edge.GetSourcePos();
909  auto dst = edge.GetTargetPos();
910 
911  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
913  edge.GetSourceNode()->Parent(),
914  wxPoint( src.x, src.y ),
915  edge.GetTargetNode()->Parent(),
916  wxPoint( dst.x, dst.y ) ) );
917 
918  }
919 }
920 
921 
923 {
924  // Test copper areas for valid netcodes
925  // if a netcode is < 0 the netname was not found when reading a netlist
926  // if a netcode is == 0 the netname is void, and the zone is not connected.
927  // This is allowed, but i am not sure this is a good idea
928  //
929  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
930  // is stored, and initialized from the file or the zone properties editor.
931  // if it differs from the net name from net code, there is a DRC issue
932  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
933  {
934  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
935 
936  if( !zone->IsOnCopperLayer() )
937  continue;
938 
939  int netcode = zone->GetNetCode();
940  // a netcode < 0 or > 0 and no pad in net is a error or strange
941  // perhaps a "dead" net, which happens when all pads in this net were removed
942  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
943  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
944 
945  if( ( netcode < 0 ) || pads_in_net == 0 )
946  {
947  wxPoint markerPos = zone->GetPosition();
949  markerPos, zone, DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE ) );
950  }
951  }
952 
953  // Test copper areas outlines, and create markers when needed
954  TestZoneToZoneOutline( NULL, true );
955 }
956 
957 
959 {
960  // Test keepout areas for vias, tracks and pads inside keepout areas
961  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
962  {
963  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
964 
965  if( !area->GetIsKeepout() )
966  {
967  continue;
968  }
969 
970  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
971  {
972  if( segm->Type() == PCB_TRACE_T )
973  {
974  if( !area->GetDoNotAllowTracks() )
975  continue;
976 
977  // Ignore if the keepout zone is not on the same layer
978  if( !area->IsOnLayer( segm->GetLayer() ) )
979  continue;
980 
981  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
982 
983  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
986  }
987  else if( segm->Type() == PCB_VIA_T )
988  {
989  if( ! area->GetDoNotAllowVias() )
990  continue;
991 
992  auto viaLayers = segm->GetLayerSet();
993 
994  if( !area->CommonLayerExists( viaLayers ) )
995  continue;
996 
997  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
1000  }
1001  }
1002  // Test pads: TODO
1003  }
1004 }
1005 
1006 
1008 {
1009  // Test copper items for clearance violations with vias, tracks and pads
1010 
1011  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
1012  {
1013  if( IsCopperLayer( brdItem->GetLayer() ) )
1014  {
1015  if( brdItem->Type() == PCB_TEXT_T )
1016  testCopperTextItem( brdItem );
1017  else if( brdItem->Type() == PCB_LINE_T )
1018  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
1019  }
1020  }
1021 
1022  for( MODULE* module : m_pcb->Modules() )
1023  {
1024  TEXTE_MODULE& ref = module->Reference();
1025  TEXTE_MODULE& val = module->Value();
1026 
1027  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
1028  testCopperTextItem( &ref );
1029 
1030  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
1031  testCopperTextItem( &val );
1032 
1033  if( module->IsNetTie() )
1034  continue;
1035 
1036  for( BOARD_ITEM* item = module->GraphicalItemsList(); item; item = item->Next() )
1037  {
1038  if( IsCopperLayer( item->GetLayer() ) )
1039  {
1040  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
1041  testCopperTextItem( item );
1042  else if( item->Type() == PCB_MODULE_EDGE_T )
1043  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
1044  }
1045  }
1046  }
1047 }
1048 
1049 
1051 {
1052  std::vector<SEG> itemShape;
1053  int itemWidth = aItem->GetWidth();
1054 
1055  switch( aItem->GetShape() )
1056  {
1057  case S_ARC:
1058  {
1059  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
1060 
1061  auto l = arc.ConvertToPolyline();
1062 
1063  for( int i = 0; i < l.SegmentCount(); i++ )
1064  itemShape.push_back( l.CSegment(i) );
1065 
1066  break;
1067  }
1068 
1069  case S_SEGMENT:
1070  itemShape.push_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
1071  break;
1072 
1073  case S_CIRCLE:
1074  {
1075  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
1076  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1077 
1078  auto l = circle.ConvertToPolyline();
1079 
1080  for( int i = 0; i < l.SegmentCount(); i++ )
1081  itemShape.push_back( l.CSegment(i) );
1082 
1083  break;
1084  }
1085 
1086  case S_CURVE:
1087  {
1088  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1089  wxPoint start_pt = aItem->GetBezierPoints()[0];
1090 
1091  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1092  {
1093  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1094  itemShape.push_back( SEG( start_pt, end_pt ) );
1095  start_pt = end_pt;
1096  }
1097 
1098  break;
1099  }
1100 
1101  default:
1102  break;
1103  }
1104 
1105  // Test tracks and vias
1106  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1107  {
1108  if( !track->IsOnLayer( aItem->GetLayer() ) )
1109  continue;
1110 
1111  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1112  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1113 
1114  for( const auto& itemSeg : itemShape )
1115  {
1116  if( trackAsSeg.Distance( itemSeg ) < minDist )
1117  {
1118  if( track->Type() == PCB_VIA_T )
1120  track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1121  else
1123  track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1124  break;
1125  }
1126  }
1127  }
1128 
1129  // Test pads
1130  for( auto pad : m_pcb->GetPads() )
1131  {
1132  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1133  continue;
1134 
1135  // Graphic items are allowed to act as net-ties within their own footprint
1136  if( pad->GetParent() == aItem->GetParent() )
1137  continue;
1138 
1139  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1140  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1141  SHAPE_POLY_SET padOutline;
1142 
1143  // We incorporate "minDist" into the pad's outline
1144  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ),
1145  segmentCount, correctionFactor );
1146 
1147  for( const auto& itemSeg : itemShape )
1148  {
1149  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1150  {
1152  break;
1153  }
1154  }
1155  }
1156 }
1157 
1158 
1160 {
1161  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1162 
1163  if( text == nullptr )
1164  return;
1165 
1166  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1167  int textWidth = text->GetThickness();
1168 
1169  // So far the bounding box makes up the text-area
1170  text->TransformTextShapeToSegmentList( textShape );
1171 
1172  if( textShape.size() == 0 ) // Should not happen (empty text?)
1173  return;
1174 
1175  EDA_RECT bbox = text->GetTextBox();
1176  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1177 
1178  // Test tracks and vias
1179  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1180  {
1181  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1182  continue;
1183 
1184  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1185  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1186 
1187  // Fast test to detect a trach segment candidate inside the text bounding box
1188  if( !rect_area.Collide( trackAsSeg, minDist ) )
1189  continue;
1190 
1191  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1192  {
1193  SEG textSeg( textShape[jj], textShape[jj+1] );
1194 
1195  if( trackAsSeg.Distance( textSeg ) < minDist )
1196  {
1197  if( track->Type() == PCB_VIA_T )
1199  track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1200  else
1202  track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
1203  break;
1204  }
1205  }
1206  }
1207 
1208  // Test pads
1209  for( auto pad : m_pcb->GetPads() )
1210  {
1211  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1212  continue;
1213 
1214  // Fast test to detect a pad candidate inside the text bounding box
1215  // Finer test (time consumming) is made only for pads near the text.
1216  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1217  VECTOR2I shape_pos( pad->ShapePos() );
1218 
1219  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1220  continue;
1221 
1222  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1223  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1224  SHAPE_POLY_SET padOutline;
1225 
1226  int minDist = textWidth/2 + pad->GetClearance( NULL );
1227  pad->TransformShapeWithClearanceToPolygon( padOutline, 0,
1228  segmentCount, correctionFactor );
1229 
1230  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1231  {
1232  SEG textSeg( textShape[jj], textShape[jj+1] );
1233 
1234  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1235  {
1237  break;
1238  }
1239  }
1240  }
1241 }
1242 
1243 
1245 {
1246  wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
1247 
1249 
1250  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1251  {
1253  return;
1254  }
1255 }
1256 
1257 
1259 {
1260  BOARD* board = m_pcbEditorFrame->GetBoard();
1261  wxCHECK( board, /*void*/ );
1262  LSET disabledLayers = board->GetEnabledLayers().flip();
1263 
1264  // Perform the test only for copper layers
1265  disabledLayers &= LSET::AllCuMask();
1266 
1267  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1269  aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1270  };
1271 
1272  for( auto track : board->Tracks() )
1273  {
1274  if( disabledLayers.test( track->GetLayer() ) )
1275  createMarker( track );
1276  }
1277 
1278  for( auto module : board->Modules() )
1279  {
1280  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1281  {
1282  if( disabledLayers.test( aItem->GetLayer() ) )
1283  createMarker( aItem );
1284  } );
1285  }
1286 
1287  for( auto zone : board->Zones() )
1288  {
1289  if( disabledLayers.test( zone->GetLayer() ) )
1290  createMarker( zone );
1291  }
1292 }
1293 
1294 
1296 {
1297  // Test keepout areas for vias, tracks and pads inside keepout areas
1298  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
1299  {
1300  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
1301 
1302  if( !area->GetIsKeepout() )
1303  continue;
1304 
1305  if( aRefSeg->Type() == PCB_TRACE_T )
1306  {
1307  if( !area->GetDoNotAllowTracks() )
1308  continue;
1309 
1310  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
1311  continue;
1312 
1313  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
1314  aRefSeg->GetWidth() ) == 0 )
1315  {
1316  m_currentMarker =
1318  return false;
1319  }
1320  }
1321  else if( aRefSeg->Type() == PCB_VIA_T )
1322  {
1323  if( !area->GetDoNotAllowVias() )
1324  continue;
1325 
1326  auto viaLayers = aRefSeg->GetLayerSet();
1327 
1328  if( !area->CommonLayerExists( viaLayers ) )
1329  continue;
1330 
1331  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1332  {
1333  m_currentMarker =
1335  return false;
1336  }
1337  }
1338  }
1339 
1340  return true;
1341 }
1342 
1343 
1344 bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit )
1345 {
1346  const static LSET all_cu = LSET::AllCuMask();
1347 
1348  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1349 
1350  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1351  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1352  * Therefore, this dummy pad is a circle or an oval.
1353  * A pad must have a parent because some functions expect a non null parent
1354  * to find the parent board, and some other data
1355  */
1356  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1357  D_PAD dummypad( &dummymodule );
1358 
1359  // Ensure the hole is on all copper layers
1360  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1361 
1362  // Use the minimal local clearance value for the dummy pad.
1363  // The clearance of the active pad will be used as minimum distance to a hole
1364  // (a value = 0 means use netclass value)
1365  dummypad.SetLocalClearance( 1 );
1366 
1367  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1368  {
1369  D_PAD* pad = *pad_list;
1370 
1371  if( pad == aRefPad )
1372  continue;
1373 
1374  // We can stop the test when pad->GetPosition().x > x_limit
1375  // because the list is sorted by X values
1376  if( pad->GetPosition().x > x_limit )
1377  break;
1378 
1379  // No problem if pads which are on copper layers are on different copper layers,
1380  // (pads can be only on a technical layer, to build complex pads)
1381  // but their hole (if any ) can create DRC error because they are on all
1382  // copper layers, so we test them
1383  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1384  ( pad->GetLayerSet() & all_cu ) != 0 &&
1385  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1386  {
1387  // if holes are in the same location and have the same size and shape,
1388  // this can be accepted
1389  if( pad->GetPosition() == aRefPad->GetPosition()
1390  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1391  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1392  {
1393  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1394  continue;
1395 
1396  // for oval holes: must also have the same orientation
1397  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1398  continue;
1399  }
1400 
1401  /* Here, we must test clearance between holes and pads
1402  * dummy pad size and shape is adjusted to pad drill size and shape
1403  */
1404  if( pad->GetDrillSize().x )
1405  {
1406  // pad under testing has a hole, test this hole against pad reference
1407  dummypad.SetPosition( pad->GetPosition() );
1408  dummypad.SetSize( pad->GetDrillSize() );
1409  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1411  dummypad.SetOrientation( pad->GetOrientation() );
1412 
1413  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1414  {
1415  // here we have a drc error on pad!
1417  return false;
1418  }
1419  }
1420 
1421  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1422  {
1423  dummypad.SetPosition( aRefPad->GetPosition() );
1424  dummypad.SetSize( aRefPad->GetDrillSize() );
1425  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1427  dummypad.SetOrientation( aRefPad->GetOrientation() );
1428 
1429  if( !checkClearancePadToPad( pad, &dummypad ) )
1430  {
1431  // here we have a drc error on aRefPad!
1433  return false;
1434  }
1435  }
1436 
1437  continue;
1438  }
1439 
1440  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1441  // But no problem if pads have the same netcode (same net)
1442  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1443  continue;
1444 
1445  // if pads are from the same footprint
1446  if( pad->GetParent() == aRefPad->GetParent() )
1447  {
1448  // and have the same pad number ( equivalent pads )
1449 
1450  // one can argue that this 2nd test is not necessary, that any
1451  // two pads from a single module are acceptable. This 2nd test
1452  // should eventually be a configuration option.
1453  if( pad->PadNameEqual( aRefPad ) )
1454  continue;
1455  }
1456 
1457  // if either pad has no drill and is only on technical layers, not a clearance violation
1458  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1459  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1460  {
1461  continue;
1462  }
1463 
1464  if( !checkClearancePadToPad( aRefPad, pad ) )
1465  {
1466  // here we have a drc error!
1468  return false;
1469  }
1470  }
1471 
1472  return true;
1473 }
1474 
1475 
1477 {
1478  DRC_COURTYARD_OVERLAP drc_overlap(
1479  m_markerFactory, [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1480 
1481  drc_overlap.RunDRC( *m_pcb );
1482 }
1483 
1484 
1485 void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS_T aUnits,
1486  DRC_LIST& aDRCList )
1487 {
1488  MODULE* module;
1489  MODULE* nextModule;
1490 
1491  // Search for duplicate footprints.
1492  for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
1493  {
1494  nextModule = module->Next();
1495 
1496  for( ; nextModule != NULL; nextModule = nextModule->Next() )
1497  {
1498  if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
1499  {
1500  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_DUPLICATE_FOOTPRINT,
1501  module, module->GetPosition(),
1502  nextModule, nextModule->GetPosition() ) );
1503  break;
1504  }
1505  }
1506  }
1507 
1508  // Search for component footprints in the netlist but not on the board.
1509  for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
1510  {
1511  COMPONENT* component = aNetlist.GetComponent( ii );
1512 
1513  module = aPCB->FindModuleByReference( component->GetReference() );
1514 
1515  if( module == NULL )
1516  {
1517  wxString msg = wxString::Format( wxT( "%s (%s)" ),
1518  component->GetReference(),
1519  component->GetValue() );
1520 
1521  aDRCList.emplace_back( new DRC_ITEM( DRCE_MISSING_FOOTPRINT, msg ) );
1522  }
1523  }
1524 
1525  // Search for component footprints found on board but not in netlist.
1526  for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
1527  {
1528 
1529  COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
1530 
1531  if( component == NULL )
1532  {
1533  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_EXTRA_FOOTPRINT,
1534  module, module->GetPosition(),
1535  nullptr, wxPoint() ) );
1536  }
1537  }
1538 }
1539 
1540 
bool m_refillZones
Definition: drc.h:200
#define DRCE_EXTRA_FOOTPRINT
netlist item not found for footprint
Definition: drc.h:104
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
Definition: drc.cpp:605
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
#define DRCE_DISABLED_LAYER_ITEM
item on a disabled layer
Definition: drc.h:98
bool m_doCreateRptFile
Definition: drc.h:199
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
#define OK_DRC
Definition: drc.h:39
void DestroyDRCDialog(int aReason)
Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.
Definition: drc.cpp:123
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
int GetNetCode() const
Function GetNetCode.
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:200
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:722
TEXTE_PCB class definition.
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set.
Definition: class_zone.cpp:204
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
void testCopperTextAndGraphics()
Definition: drc.cpp:1007
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:118
#define DRCE_PAD_NEAR_PAD1
pad too close to pad
Definition: drc.h:66
int TestZoneToZoneOutline(ZONE_CONTAINER *aZone, bool aCreateMarkers)
Tests whether distance between zones complies with the DRC rules.
Definition: drc.cpp:226
int m_ycliplo
Definition: drc.h:235
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
const wxPoint GetCenter() const override
Function GetCenter()
#define DRCE_NETCLASS_TRACKWIDTH
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc.h:79
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc.h:72
int GetX() const
Definition: eda_rect.h:109
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
DRC_LIST m_footprints
list of footprint warnings, as DRC_ITEMs
Definition: drc.h:246
const wxPoint & GetStart() const
Definition: class_track.h:133
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:802
STROKE_T GetShape() const
bool IsVisible() const
Definition: eda_text.h:193
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_zone.cpp:278
void testKeepoutAreas()
Definition: drc.cpp:958
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:209
void Check_All_Zones(wxWindow *aActiveWindow)
Function Check_All_Zones Checks for out-of-date fills and fills them if requested by the user.
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_BezierPoints vertex list that approximate the Bezier curve by a list of segments Has me...
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
static TOOL_ACTION cancelInteractive
Definition: actions.h:45
int m_ycliphi
Definition: drc.h:237
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:185
int GetWidth() const
Definition: eda_rect.h:117
#define DRCE_DRILLED_HOLES_TOO_CLOSE
overlapping drilled holes break drill bits
Definition: drc.h:99
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:209
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:85
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
Definition: drc.cpp:1050
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
#define DRCE_MISSING_FOOTPRINT
footprint not found for netlist item
Definition: drc.h:102
int m_segmLength
Definition: drc.h:229
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:221
Classes to handle copper zones.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:534
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:171
usual segment : line with rounded ends
iterator end()
Definition: netclass.h:249
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:80
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
const std::vector< wxPoint > & GetBezierPoints() const
#define DRCE_ZONES_INTERSECT
copper area outlines intersect
Definition: drc.h:69
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:89
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
Definition: drc.cpp:1244
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc.h:49
const wxPoint GetPosition() const override
Definition: class_zone.cpp:179
DRCLISTBOX * m_UnconnectedListBox
void testCopperTextItem(BOARD_ITEM *aTextItem)
Definition: drc.cpp:1159
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:251
static const int delta[8][2]
Definition: solve.cpp:112
void DeactivateTool()
Function DeactivateTool() Deactivates the currently active tool.
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:775
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:71
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
Functions relatives to tracks, vias and segments used to fill zones.
int DrcOnCreatingTrack(TRACK *aRefSeg, TRACK *aList)
Function Drc tests the current segment and returns the result and displays the error in the status pa...
Definition: drc.cpp:181
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:1295
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:462
BOARD * m_pcb
Definition: drc.h:240
bool GetDoNotAllowVias() const
Definition: class_zone.h:653
static void TestFootprints(NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS_T aUnits, DRC_LIST &aDRCList)
Test the board footprints against a netlist.
Definition: drc.cpp:1485
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:128
void testDrilledHoles()
Definition: drc.cpp:757
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool aTestPads, bool aTestZones)
Test the current segment.
Class TOOL_MANAGER.
Definition: tool_manager.h:49
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:88
#define DRCE_NETCLASS_uVIADRILLSIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc.h:84
#define DRCE_NETCLASS_VIASIZE
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc.h:81
bool m_testFootprints
Definition: drc.h:202
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
bool m_doKeepoutTest
Definition: drc.h:198
int m_HoleToHoleMin
Min width of peninsula between two drilled holes.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
Class LSET is a set of PCB_LAYER_IDs.
bool m_doZonesTest
Definition: drc.h:197
iterator begin()
Definition: netclass.h:248
Class NETCLASSES is a container for NETCLASS instances.
Definition: netclass.h:224
#define DRCE_DUPLICATE_FOOTPRINT
more than one footprints found for netlist item
Definition: drc.h:103
void SetList(EDA_UNITS_T aUnits, DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:214
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false) const
Function GetTextBox useful in multiline texts to calculate the full text or a line area (for zones fi...
Definition: eda_text.cpp:119
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:252
const wxPoint GetPosition() const override
Definition: class_track.h:124
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
void testZones()
Definition: drc.cpp:922
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
Class SHAPE_POLY_SET.
DRCLISTBOX * m_ClearanceListBox
Class DRC_LIST_MARKERS is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD i...
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:289
int m_TrackMinWidth
track min value for width ((min copper size value
const wxPoint GetPosition() const
Definition: eda_rect.h:113
Arcs (with rounded ends)
TOOL_MANAGER * GetToolManager() const override
Return the tool manager instance, if any.
Definition: draw_frame.h:937
DRC(PCB_EDIT_FRAME *aPcbWindow)
Definition: drc.cpp:135
int m_ViasMinSize
vias (not micro vias) min diameter
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:586
int DrcOnCreatingZone(ZONE_CONTAINER *aArea, int aCornerIndex)
Function Drc tests the outline segment starting at CornerIndex and returns the result and displays th...
Definition: drc.cpp:379
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:400
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:414
Class DRC_LIST_GENERIC is an implementation of the interface named DRC_ITEM_LIST which uses a vector ...
const wxString & GetReference() const
Definition: pcb_netlist.h:151
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:292
int m_ViasMinDrill
vias (not micro vias) min drill diameter
void TransformTextShapeToSegmentList(std::vector< wxPoint > &aCornerBuffer) const
Convert the text shape to a list of segment each segment is stored as 2 wxPoints: the starting point ...
Definition: eda_text.cpp:496
VIATYPE_T GetViaType() const
Definition: class_track.h:437
void SetSize(const wxSize &aSize)
Definition: class_pad.h:270
#define DRCE_INVALID_OUTLINE
invalid board outline
Definition: drc.h:101
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:624
a few functions useful in geometry calculations.
const wxPoint & GetArcStart() const
bool RunDRC(BOARD &aBoard) const override
Runs this provider against the given PCB with configured options (if any).
int GetClearanceBetweenSegments(int x1i, int y1i, int x1f, int y1f, int w1, int x2i, int y2i, int x2f, int y2f, int w2, int max_cl, int *x, int *y)
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines,...
bool m_reportAllTrackErrors
Definition: drc.h:201
std::vector< DRC_ITEM * > DRC_LIST
Definition: drc.h:177
Bezier Curve.
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:82
bool m_drcRun
Definition: drc.h:247
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
Definition: drc.cpp:1258
bool doPadToPadsDrc(D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Test the clearance between aRefPad and other pads.
Definition: drc.cpp:1344
int m_xcliphi
Definition: drc.h:236
int m_MicroViasMinSize
micro vias (not vias) min diameter
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
const wxPoint GetPosition() const override
Definition: class_track.h:410
bool m_doPad2PadTest
Definition: drc.h:195
void testPad2Pad()
Definition: drc.cpp:713
int GetHeight() const
Definition: eda_rect.h:118
#define BAD_DRC
Definition: drc.h:40
bool Show(bool show) override
void Fill_All_Zones()
Function Fill_All_Zones.
int GetWidth() const
bool doEdgeZoneDrc(ZONE_CONTAINER *aArea, int aCornerIndex)
Test a segment in ZONE_CONTAINER * aArea: Test Edge inside other areas Test Edge too close other area...
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:651
Pad object description.
void SetLocalClearance(int aClearance)
Definition: class_pad.h:430
A class that provides the courtyard-based DRC checks.
Class COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:83
#define FmtVal(x)
bool m_footprintsTested
Definition: drc.h:248
friend class DIALOG_DRC_CONTROL
Definition: drc.h:190
MODULE * GetParent() const
Definition: class_pad.h:164
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:206
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:265
Definition: seg.h:36
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
double GetAngle() const
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly if it exists,...
bool m_RequireCourtyards
require courtyard definitions in footprints
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:413
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:241
ZONE_CONTAINERS & Zones()
Definition: class_board.h:254
bool testNetClasses()
Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance ...
Definition: drc.cpp:690
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
Definition: drc.cpp:830
void ShowDRCDialog(wxWindow *aParent=NULL)
Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and create...
Definition: drc.cpp:65
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:100
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:96
BOARD_ITEM * Next() const
int GetWidth() const
Definition: class_track.h:127
wxString m_rptFilename
Definition: drc.h:204
Class to handle a graphic segment.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
DLIST< MODULE > m_Modules
Definition: class_board.h:248
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:394
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
size_t i
Definition: json11.cpp:597
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
DRCLISTBOX * m_FootprintsListBox
const wxSize & GetDrillSize() const
Definition: class_pad.h:277
VECTOR2I A
Definition: seg.h:44
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc.h:86
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
#define DRCE_ZONES_TOO_CLOSE
copper area outlines are too close
Definition: drc.h:70
Class PCB_EDIT_FRAME is the main frame for Pcbnew.
int GetY() const
Definition: eda_rect.h:110
#define DRCE_PAD_NEAR_COPPER
pad and copper graphic collide or are too close
Definition: drc.h:90
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:608
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true) override
Executes the changes.
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:219
const wxPoint & GetEnd() const
Definition: class_track.h:130
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:429
bool GetDoNotAllowTracks() const
Definition: class_zone.h:654
MODULE * Next() const
Definition: class_module.h:122
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:268
const wxString & GetValue() const
Definition: pcb_netlist.h:153
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:251
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
DLIST< TRACK > m_Track
Definition: class_board.h:249
Module description (excepted pads)
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:952
BOARD * GetBoard() const
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:245
const wxPoint GetPosition() const override
Definition: class_pad.h:222
void SetUnitsProvider(UNITS_PROVIDER aUnitsProvider)
Set the provider for the units (this will be called for each new marker constructed)
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
~DRC()
Definition: drc.cpp:171
void testUnconnected()
Definition: drc.cpp:890
void RunTests(wxTextCtrl *aMessages=NULL)
Run all the tests specified with a previous call to SetSettings()
Definition: drc.cpp:406
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:214
BOARD_ITEM_CONTAINER * GetParent() const
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=500.0) const
Constructs a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:240
#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF
Definition: pcbnew.h:42
int m_xcliplo
Definition: drc.h:234
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
const wxPoint GetPosition() const override
Definition: class_module.h:183
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:191
#define DRCE_NETCLASS_uVIASIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc.h:83
#define mod(a, n)
Definition: greymap.cpp:24
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
EDA_UNITS_T
Definition: common.h:157
bool m_doUnconnectedTest
Definition: drc.h:196
double m_segmAngle
Definition: drc.h:228
void doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1476
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:253
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:202
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
KICAD_T Type() const
Function Type()
Definition: base_struct.h:204
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
EDA_UNITS_T GetUserUnits() const override
Definition: dialog_shim.h:133
VECTOR2I B
Definition: seg.h:45
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)