KiCad PCB EDA Suite
pcbnew/tools/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 
26 #include <fctsys.h>
27 #include <pcb_edit_frame.h>
28 #include <trigo.h>
29 #include <board_design_settings.h>
30 #include <class_edge_mod.h>
31 #include <class_drawsegment.h>
32 #include <class_module.h>
33 #include <class_track.h>
34 #include <class_pad.h>
35 #include <class_zone.h>
36 #include <class_pcb_text.h>
37 #include <class_draw_panel_gal.h>
38 #include <view/view.h>
39 #include <geometry/seg.h>
40 #include <math_for_graphics.h>
44 #include <bitmaps.h>
45 #include <tool/tool_manager.h>
46 #include <tools/pcb_actions.h>
47 #include <tools/pcb_tool_base.h>
48 #include <kiface_i.h>
49 #include <pcbnew.h>
50 #include <tools/drc.h>
52 #include <math/util.h> // for KiROUND
53 
54 #include <dialog_drc.h>
55 #include <wx/progdlg.h>
56 #include <board_commit.h>
57 #include <geometry/shape_segment.h>
58 #include <geometry/shape_arc.h>
59 
60 #include <drc/courtyard_overlap.h>
61 #include "zone_filler_tool.h"
62 
64  PCB_TOOL_BASE( "pcbnew.DRCTool" ),
65  m_currentMarker( nullptr ),
66  m_pcbEditorFrame( nullptr ),
67  m_pcb( nullptr ),
68  m_drcDialog( nullptr )
69 {
70  // establish initial values for everything:
71  m_doPad2PadTest = true; // enable pad to pad clearance tests
72  m_doUnconnectedTest = true; // enable unconnected tests
73  m_doZonesTest = false; // disable zone to items clearance tests
74  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
75  m_refillZones = false; // Only fill zones if requested by user.
76  m_reportAllTrackErrors = false;
77  m_testFootprints = false;
78 
79  m_drcRun = false;
80  m_footprintsTested = false;
81 
82  m_doCreateRptFile = false;
83  // m_rptFilename set to empty by its constructor
84 
85  m_segmAngle = 0;
86  m_segmLength = 0;
87 
88  m_xcliplo = 0;
89  m_ycliplo = 0;
90  m_xcliphi = 0;
91  m_ycliphi = 0;
92 }
93 
94 
96 {
97  for( DRC_ITEM* unconnectedItem : m_unconnected )
98  delete unconnectedItem;
99 
100  for( DRC_ITEM* footprintItem : m_footprints )
101  delete footprintItem;
102 }
103 
104 
105 void DRC::Reset( RESET_REASON aReason )
106 {
107  m_pcbEditorFrame = getEditFrame<PCB_EDIT_FRAME>();
108 
109  if( aReason == MODEL_RELOAD )
110  {
111  if( m_drcDialog )
112  DestroyDRCDialog( wxID_OK );
113 
115 
117  }
118 }
119 
120 
121 void DRC::ShowDRCDialog( wxWindow* aParent )
122 {
123  bool show_dlg_modal = true;
124 
125  // the dialog needs a parent frame. if it is not specified, this is
126  // the PCB editor frame specified in DRC class.
127  if( !aParent )
128  {
129  // if any parent is specified, the dialog is modal.
130  // if this is the default PCB editor frame, it is not modal
131  show_dlg_modal = false;
132  aParent = m_pcbEditorFrame;
133  }
134 
135  Activate();
137 
138  if( !m_drcDialog )
139  {
140  m_drcDialog = new DIALOG_DRC_CONTROL( this, m_pcbEditorFrame, aParent );
141  updatePointers();
142 
144 
145  if( show_dlg_modal )
146  m_drcDialog->ShowModal();
147  else
148  m_drcDialog->Show( true );
149  }
150  else // The dialog is just not visible (because the user has double clicked on an error item)
151  {
152  updatePointers();
153  m_drcDialog->Show( true );
154  }
155 }
156 
157 
158 int DRC::ShowDRCDialog( const TOOL_EVENT& aEvent )
159 {
160  ShowDRCDialog( nullptr );
161  return 0;
162 }
163 
164 
166 {
167  BOARD_COMMIT commit( m_pcbEditorFrame );
168  commit.Add( aMarker );
169  commit.Push( wxEmptyString, false, false );
170 }
171 
172 
173 void DRC::DestroyDRCDialog( int aReason )
174 {
175  if( m_drcDialog )
176  {
178 
179  m_drcDialog->Destroy();
180  m_drcDialog = nullptr;
181  }
182 }
183 
184 
185 int DRC::TestZoneToZoneOutline( ZONE_CONTAINER* aZone, bool aCreateMarkers )
186 {
188  BOARD_COMMIT commit( m_pcbEditorFrame );
189  int nerrors = 0;
190 
191  std::vector<SHAPE_POLY_SET> smoothed_polys;
192  smoothed_polys.resize( board->GetAreaCount() );
193 
194  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
195  {
196  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
197  std::set<VECTOR2I> colinearCorners;
198  zoneRef->GetColinearCorners( board, colinearCorners );
199 
200  zoneRef->BuildSmoothedPoly( smoothed_polys[ia], &colinearCorners );
201  }
202 
203  // iterate through all areas
204  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
205  {
206  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
207 
208  if( !zoneRef->IsOnCopperLayer() )
209  continue;
210 
211  // When testing only a single area, skip all others
212  if( aZone && ( aZone != zoneRef) )
213  continue;
214 
215  // If we are testing a single zone, then iterate through all other zones
216  // Otherwise, we have already tested the zone combination
217  for( int ia2 = ( aZone ? 0 : ia + 1 ); ia2 < board->GetAreaCount(); ia2++ )
218  {
219  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
220 
221  if( zoneRef == zoneToTest )
222  continue;
223 
224  // test for same layer
225  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
226  continue;
227 
228  // Test for same net
229  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
230  continue;
231 
232  // test for different priorities
233  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
234  continue;
235 
236  // test for different types
237  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
238  continue;
239 
240  // Examine a candidate zone: compare zoneToTest to zoneRef
241 
242  // Get clearance used in zone to zone test. The policy used to
243  // obtain that value is now part of the zone object itself by way of
244  // ZONE_CONTAINER::GetClearance().
245  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
246 
247  // Keepout areas have no clearance, so set zone2zoneClearance to 1
248  // ( zone2zoneClearance = 0 can create problems in test functions)
249  if( zoneRef->GetIsKeepout() )
250  zone2zoneClearance = 1;
251 
252  // test for some corners of zoneRef inside zoneToTest
253  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
254  {
255  VECTOR2I currentVertex = *iterator;
256  wxPoint pt( currentVertex.x, currentVertex.y );
257 
258  if( smoothed_polys[ia2].Contains( currentVertex ) )
259  {
260  if( aCreateMarkers )
261  commit.Add( m_markerFactory.NewMarker( pt, zoneRef, zoneToTest,
263 
264  nerrors++;
265  }
266  }
267 
268  // test for some corners of zoneToTest inside zoneRef
269  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
270  {
271  VECTOR2I currentVertex = *iterator;
272  wxPoint pt( currentVertex.x, currentVertex.y );
273 
274  if( smoothed_polys[ia].Contains( currentVertex ) )
275  {
276  if( aCreateMarkers )
277  commit.Add( m_markerFactory.NewMarker( pt, zoneToTest, zoneRef,
279 
280  nerrors++;
281  }
282  }
283 
284  // Iterate through all the segments of refSmoothedPoly
285  std::set<wxPoint> conflictPoints;
286 
287  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
288  {
289  // Build ref segment
290  SEG refSegment = *refIt;
291 
292  // Iterate through all the segments in smoothed_polys[ia2]
293  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
294  {
295  // Build test segment
296  SEG testSegment = *testIt;
297  wxPoint pt;
298 
299  int ax1, ay1, ax2, ay2;
300  ax1 = refSegment.A.x;
301  ay1 = refSegment.A.y;
302  ax2 = refSegment.B.x;
303  ay2 = refSegment.B.y;
304 
305  int bx1, by1, bx2, by2;
306  bx1 = testSegment.A.x;
307  by1 = testSegment.A.y;
308  bx2 = testSegment.B.x;
309  by2 = testSegment.B.y;
310 
311  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
312  0,
313  ax1, ay1, ax2, ay2,
314  0,
315  zone2zoneClearance,
316  &pt.x, &pt.y );
317 
318  if( d < zone2zoneClearance )
319  conflictPoints.insert( pt );
320  }
321  }
322 
323  for( wxPoint pt : conflictPoints )
324  {
325  if( aCreateMarkers )
326  commit.Add( m_markerFactory.NewMarker( pt, zoneRef, zoneToTest,
328 
329  nerrors++;
330  }
331  }
332  }
333 
334  if( aCreateMarkers )
335  commit.Push( wxEmptyString, false, false );
336 
337  return nerrors;
338 }
339 
340 
341 void DRC::RunTests( wxTextCtrl* aMessages )
342 {
343  // be sure m_pcb is the current board, not a old one
344  // ( the board can be reloaded )
346 
347  if( aMessages )
348  {
349  aMessages->AppendText( _( "Board Outline...\n" ) );
350  wxSafeYield();
351  }
352 
353  testOutline();
354 
355  // someone should have cleared the two lists before calling this.
356  if( !testNetClasses() )
357  {
358  // testing the netclasses is a special case because if the netclasses
359  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
360  // class (a NET) will cause its items such as tracks, vias, and pads
361  // to also fail. So quit after *all* netclass errors have been reported.
362  if( aMessages )
363  aMessages->AppendText( _( "Aborting\n" ) );
364 
365  // update the m_drcDialog listboxes
366  updatePointers();
367 
368  return;
369  }
370 
371  // test pad to pad clearances, nothing to do with tracks, vias or zones.
372  if( m_doPad2PadTest )
373  {
374  if( aMessages )
375  {
376  aMessages->AppendText( _( "Pad clearances...\n" ) );
377  wxSafeYield();
378  }
379 
380  testPad2Pad();
381  }
382 
383  // test clearances between drilled holes
384  if( aMessages )
385  {
386  aMessages->AppendText( _( "Drill clearances...\n" ) );
387  wxSafeYield();
388  }
389 
391 
392  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
393  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
394 
395  if( m_refillZones )
396  {
397  if( aMessages )
398  aMessages->AppendText( _( "Refilling all zones...\n" ) );
399 
400  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->FillAllZones( caller );
401  }
402  else
403  {
404  if( aMessages )
405  aMessages->AppendText( _( "Checking zone fills...\n" ) );
406 
407  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( caller );
408  }
409 
410  // test track and via clearances to other tracks, pads, and vias
411  if( aMessages )
412  {
413  aMessages->AppendText( _( "Track clearances...\n" ) );
414  wxSafeYield();
415  }
416 
417  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
418 
419  // test zone clearances to other zones
420  if( aMessages )
421  {
422  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
423  wxSafeYield();
424  }
425 
426  testZones();
427 
428  // find and gather unconnected pads.
429  if( m_doUnconnectedTest )
430  {
431  if( aMessages )
432  {
433  aMessages->AppendText( _( "Unconnected pads...\n" ) );
434  aMessages->Refresh();
435  }
436 
437  testUnconnected();
438  }
439 
440  // find and gather vias, tracks, pads inside keepout areas.
441  if( m_doKeepoutTest )
442  {
443  if( aMessages )
444  {
445  aMessages->AppendText( _( "Keepout areas ...\n" ) );
446  aMessages->Refresh();
447  }
448 
450  }
451 
452  // find and gather vias, tracks, pads inside text boxes.
453  if( aMessages )
454  {
455  aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
456  wxSafeYield();
457  }
458 
460 
461  // find overlapping courtyard ares.
464  {
465  if( aMessages )
466  {
467  aMessages->AppendText( _( "Courtyard areas...\n" ) );
468  aMessages->Refresh();
469  }
470 
472  }
473 
474  for( DRC_ITEM* footprintItem : m_footprints )
475  delete footprintItem;
476 
477  m_footprints.clear();
478  m_footprintsTested = false;
479 
480  if( m_testFootprints && !Kiface().IsSingle() )
481  {
482  if( aMessages )
483  {
484  aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
485  aMessages->Refresh();
486  }
487 
488  NETLIST netlist;
490 
491  if( m_drcDialog )
492  m_drcDialog->Raise();
493 
495  m_footprintsTested = true;
496  }
497 
498  // Check if there are items on disabled layers
500 
501  if( aMessages )
502  {
503  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
504  aMessages->Refresh();
505  }
506 
507  m_drcRun = true;
508 
509  // update the m_drcDialog listboxes
510  updatePointers();
511 
512  if( aMessages )
513  {
514  // no newline on this one because it is last, don't want the window
515  // to unnecessarily scroll.
516  aMessages->AppendText( _( "Finished" ) );
517  }
518 }
519 
520 
522 {
523  // update my pointers, m_pcbEditorFrame is the only unchangeable one
525 
526  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
527  {
534 
536  }
537 }
538 
539 
540 bool DRC::doNetClass( const NETCLASSPTR& nc, wxString& msg )
541 {
542  bool ret = true;
543 
545 
546 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
547 
548 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
549  if( nc->GetClearance() < g.m_MinClearance )
550  {
551  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
552  GetChars( nc->GetName() ),
553  FmtVal( nc->GetClearance() ),
554  FmtVal( g.m_TrackClearance )
555  );
556 
558  m_currentMarker = nullptr;
559  ret = false;
560  }
561 #endif
562 
563  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
564  {
565  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
566  GetChars( nc->GetName() ),
567  FmtVal( nc->GetTrackWidth() ),
569  );
570 
572  ret = false;
573  }
574 
575  if( nc->GetViaDiameter() < g.m_ViasMinSize )
576  {
577  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
578  GetChars( nc->GetName() ),
579  FmtVal( nc->GetViaDiameter() ),
580  FmtVal( g.m_ViasMinSize )
581  );
582 
584  ret = false;
585  }
586 
587  if( nc->GetViaDrill() < g.m_ViasMinDrill )
588  {
589  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
590  GetChars( nc->GetName() ),
591  FmtVal( nc->GetViaDrill() ),
593  );
594 
596  ret = false;
597  }
598 
599  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
600  {
601  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
602  GetChars( nc->GetName() ),
603  FmtVal( nc->GetuViaDiameter() ),
604  FmtVal( g.m_MicroViasMinSize ) );
605 
607  ret = false;
608  }
609 
610  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
611  {
612  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
613  GetChars( nc->GetName() ),
614  FmtVal( nc->GetuViaDrill() ),
616 
618  ret = false;
619  }
620 
621  return ret;
622 }
623 
624 
626 {
627  bool ret = true;
628 
630 
631  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
632 
633  if( !doNetClass( netclasses.GetDefault(), msg ) )
634  ret = false;
635 
636  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
637  {
638  NETCLASSPTR nc = i->second;
639 
640  if( !doNetClass( nc, msg ) )
641  ret = false;
642  }
643 
644  return ret;
645 }
646 
647 
649 {
650  std::vector<D_PAD*> sortedPads;
651 
652  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
653 
654  if( sortedPads.empty() )
655  return;
656 
657  // find the max size of the pads (used to stop the test)
658  int max_size = 0;
659 
660  for( D_PAD* pad : sortedPads )
661  {
662  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
663  int radius = pad->GetBoundingRadius();
664 
665  if( radius > max_size )
666  max_size = radius;
667  }
668 
669  // Upper limit of pad list (limit not included)
670  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
671 
672  // Test the pads
673  for( auto& pad : sortedPads )
674  {
675  int x_limit = pad->GetClearance() + pad->GetBoundingRadius() + pad->GetPosition().x;
676 
677  if( !doPadToPadsDrc( pad, &pad, listEnd, max_size + x_limit ) )
678  {
679  wxASSERT( m_currentMarker );
681  m_currentMarker = nullptr;
682  }
683  }
684 }
685 
686 
688 {
689  int holeToHoleMin = m_pcb->GetDesignSettings().m_HoleToHoleMin;
690 
691  if( holeToHoleMin == 0 ) // No min setting turns testing off.
692  return;
693 
694  // Test drilled hole clearances to minimize drill bit breakage.
695  //
696  // Notes: slots are milled, so we're only concerned with circular holes
697  // microvias are laser-drilled, so we're only concerned with standard vias
698 
699  struct DRILLED_HOLE
700  {
701  wxPoint m_location;
702  int m_drillRadius;
703  BOARD_ITEM* m_owner;
704  };
705 
706  std::vector<DRILLED_HOLE> holes;
707  DRILLED_HOLE hole;
708 
709  for( MODULE* mod : m_pcb->Modules() )
710  {
711  for( D_PAD* pad : mod->Pads( ) )
712  {
713  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
714  {
715  hole.m_location = pad->GetPosition();
716  hole.m_drillRadius = pad->GetDrillSize().x / 2;
717  hole.m_owner = pad;
718  holes.push_back( hole );
719  }
720  }
721  }
722 
723  for( TRACK* track : m_pcb->Tracks() )
724  {
725  VIA* via = dynamic_cast<VIA*>( track );
726  if( via && via->GetViaType() == VIATYPE::THROUGH )
727  {
728  hole.m_location = via->GetPosition();
729  hole.m_drillRadius = via->GetDrillValue() / 2;
730  hole.m_owner = via;
731  holes.push_back( hole );
732  }
733  }
734 
735  for( size_t ii = 0; ii < holes.size(); ++ii )
736  {
737  const DRILLED_HOLE& refHole = holes[ ii ];
738 
739  for( size_t jj = ii + 1; jj < holes.size(); ++jj )
740  {
741  const DRILLED_HOLE& checkHole = holes[ jj ];
742 
743  // Holes with identical locations are allowable
744  if( checkHole.m_location == refHole.m_location )
745  continue;
746 
747  if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
748  < checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
749  {
751  DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
752  refHole.m_owner, refHole.m_location,
753  checkHole.m_owner, checkHole.m_location ) );
754  }
755  }
756  }
757 }
758 
759 
760 void DRC::testTracks( wxWindow *aActiveWindow, bool aShowProgressBar )
761 {
762  wxProgressDialog * progressDialog = NULL;
763  const int delta = 500; // This is the number of tests between 2 calls to the
764  // progress bar
765  int count = m_pcb->Tracks().size();
766 
767  int deltamax = count/delta;
768 
769  if( aShowProgressBar && deltamax > 3 )
770  {
771  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
772  // on OSX
773  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
774  deltamax, aActiveWindow,
775  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
776  progressDialog->Update( 0, wxEmptyString );
777  }
778 
779  int ii = 0;
780  count = 0;
781 
782  for( auto seg_it = m_pcb->Tracks().begin(); seg_it != m_pcb->Tracks().end(); seg_it++ )
783  {
784  if( ii++ > delta )
785  {
786  ii = 0;
787  count++;
788 
789  if( progressDialog )
790  {
791  if( !progressDialog->Update( count, wxEmptyString ) )
792  break; // Aborted by user
793 #ifdef __WXMAC__
794  // Work around a dialog z-order issue on OS X
795  if( count == deltamax )
796  aActiveWindow->Raise();
797 #endif
798  }
799  }
800 
801  // Test new segment against tracks and pads, optionally against copper zones
802  if( !doTrackDrc( *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_doZonesTest ) )
803  {
804  if( m_currentMarker )
805  {
807  m_currentMarker = nullptr;
808  }
809  }
810  }
811 
812  if( progressDialog )
813  progressDialog->Destroy();
814 }
815 
816 
818 {
819  for( DRC_ITEM* unconnectedItem : m_unconnected )
820  delete unconnectedItem;
821 
822  m_unconnected.clear();
823 
824  auto connectivity = m_pcb->GetConnectivity();
825 
826  connectivity->Clear();
827  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
828  connectivity->RecalculateRatsnest();
829 
830  std::vector<CN_EDGE> edges;
831  connectivity->GetUnconnectedEdges( edges );
832 
833  for( const auto& edge : edges )
834  {
835  auto src = edge.GetSourcePos();
836  auto dst = edge.GetTargetPos();
837 
838  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
840  edge.GetSourceNode()->Parent(),
841  wxPoint( src.x, src.y ),
842  edge.GetTargetNode()->Parent(),
843  wxPoint( dst.x, dst.y ) ) );
844  }
845 }
846 
847 
849 {
850  // Test copper areas for valid netcodes
851  // if a netcode is < 0 the netname was not found when reading a netlist
852  // if a netcode is == 0 the netname is void, and the zone is not connected.
853  // This is allowed, but i am not sure this is a good idea
854  //
855  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
856  // is stored, and initialized from the file or the zone properties editor.
857  // if it differs from the net name from net code, there is a DRC issue
858  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
859  {
860  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
861 
862  if( !zone->IsOnCopperLayer() )
863  continue;
864 
865  int netcode = zone->GetNetCode();
866  // a netcode < 0 or > 0 and no pad in net is a error or strange
867  // perhaps a "dead" net, which happens when all pads in this net were removed
868  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
869  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
870 
871  if( ( netcode < 0 ) || pads_in_net == 0 )
872  {
873  wxPoint markerPos = zone->GetPosition();
874  addMarkerToPcb( m_markerFactory.NewMarker( markerPos, zone,
876  }
877  }
878 
879  // Test copper areas outlines, and create markers when needed
880  TestZoneToZoneOutline( NULL, true );
881 }
882 
883 
885 {
886  // Get a list of all zones to inspect, from both board and footprints
887  std::list<ZONE_CONTAINER*> areasToInspect = m_pcb->GetZoneList( true );
888 
889  // Test keepout areas for vias, tracks and pads inside keepout areas
890  for( ZONE_CONTAINER* area : areasToInspect )
891  {
892 
893  if( !area->GetIsKeepout() )
894  continue;
895 
896  for( auto segm : m_pcb->Tracks() )
897  {
898  if( segm->Type() == PCB_TRACE_T )
899  {
900  if( !area->GetDoNotAllowTracks() )
901  continue;
902 
903  // Ignore if the keepout zone is not on the same layer
904  if( !area->IsOnLayer( segm->GetLayer() ) )
905  continue;
906 
907  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
908 
909  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
912  }
913  else if( segm->Type() == PCB_VIA_T )
914  {
915  if( ! area->GetDoNotAllowVias() )
916  continue;
917 
918  auto viaLayers = segm->GetLayerSet();
919 
920  if( !area->CommonLayerExists( viaLayers ) )
921  continue;
922 
923  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
926  }
927  }
928  // Test pads: TODO
929  }
930 }
931 
932 
934 {
935  // Test copper items for clearance violations with vias, tracks and pads
936 
937  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
938  {
939  if( IsCopperLayer( brdItem->GetLayer() ) )
940  {
941  if( brdItem->Type() == PCB_TEXT_T )
942  testCopperTextItem( brdItem );
943  else if( brdItem->Type() == PCB_LINE_T )
944  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
945  }
946  }
947 
948  for( MODULE* module : m_pcb->Modules() )
949  {
950  TEXTE_MODULE& ref = module->Reference();
951  TEXTE_MODULE& val = module->Value();
952 
953  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
954  testCopperTextItem( &ref );
955 
956  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
957  testCopperTextItem( &val );
958 
959  if( module->IsNetTie() )
960  continue;
961 
962  for( auto item : module->GraphicalItems() )
963  {
964  if( IsCopperLayer( item->GetLayer() ) )
965  {
966  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
967  testCopperTextItem( item );
968  else if( item->Type() == PCB_MODULE_EDGE_T )
969  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
970  }
971  }
972  }
973 }
974 
975 
977 {
978  std::vector<SEG> itemShape;
979  int itemWidth = aItem->GetWidth();
980 
981  switch( aItem->GetShape() )
982  {
983  case S_ARC:
984  {
985  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
986 
987  auto l = arc.ConvertToPolyline();
988 
989  for( int i = 0; i < l.SegmentCount(); i++ )
990  itemShape.push_back( l.Segment( i ) );
991 
992  break;
993  }
994 
995  case S_SEGMENT:
996  itemShape.emplace_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
997  break;
998 
999  case S_CIRCLE:
1000  {
1001  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
1002  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1003 
1004  auto l = circle.ConvertToPolyline();
1005 
1006  for( int i = 0; i < l.SegmentCount(); i++ )
1007  itemShape.push_back( l.Segment( i ) );
1008 
1009  break;
1010  }
1011 
1012  case S_CURVE:
1013  {
1014  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1015  wxPoint start_pt = aItem->GetBezierPoints()[0];
1016 
1017  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1018  {
1019  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1020  itemShape.emplace_back( SEG( start_pt, end_pt ) );
1021  start_pt = end_pt;
1022  }
1023 
1024  break;
1025  }
1026 
1027  default:
1028  break;
1029  }
1030 
1031  // Test tracks and vias
1032  for( auto track : m_pcb->Tracks() )
1033  {
1034  if( !track->IsOnLayer( aItem->GetLayer() ) )
1035  continue;
1036 
1037  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1038  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1039 
1040  for( const auto& itemSeg : itemShape )
1041  {
1042  if( trackAsSeg.Distance( itemSeg ) < minDist )
1043  {
1044  if( track->Type() == PCB_VIA_T )
1046  track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1047  else
1049  track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1050  break;
1051  }
1052  }
1053  }
1054 
1055  // Test pads
1056  for( auto pad : m_pcb->GetPads() )
1057  {
1058  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1059  continue;
1060 
1061  // Graphic items are allowed to act as net-ties within their own footprint
1062  if( pad->GetParent() == aItem->GetParent() )
1063  continue;
1064 
1065  SHAPE_POLY_SET padOutline;
1066  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ) );
1067 
1068  for( const auto& itemSeg : itemShape )
1069  {
1070  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1071  {
1073  break;
1074  }
1075  }
1076  }
1077 }
1078 
1079 
1081 {
1082  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1083 
1084  if( text == nullptr )
1085  return;
1086 
1087  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1088  int textWidth = text->GetThickness();
1089 
1090  // So far the bounding box makes up the text-area
1091  text->TransformTextShapeToSegmentList( textShape );
1092 
1093  if( textShape.size() == 0 ) // Should not happen (empty text?)
1094  return;
1095 
1096  EDA_RECT bbox = text->GetTextBox();
1097  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1098 
1099  // Test tracks and vias
1100  for( auto track : m_pcb->Tracks() )
1101  {
1102  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1103  continue;
1104 
1105  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1106  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1107 
1108  // Fast test to detect a trach segment candidate inside the text bounding box
1109  if( !rect_area.Collide( trackAsSeg, minDist ) )
1110  continue;
1111 
1112  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1113  {
1114  SEG textSeg( textShape[jj], textShape[jj+1] );
1115 
1116  if( trackAsSeg.Distance( textSeg ) < minDist )
1117  {
1118  if( track->Type() == PCB_VIA_T )
1120  track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1121  else
1123  track, aTextItem, textSeg, 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( aTextItem->GetLayer() ) )
1133  continue;
1134 
1135  // Fast test to detect a pad candidate inside the text bounding box
1136  // Finer test (time consumming) is made only for pads near the text.
1137  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1138  VECTOR2I shape_pos( pad->ShapePos() );
1139 
1140  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1141  continue;
1142 
1143  SHAPE_POLY_SET padOutline;
1144 
1145  int minDist = textWidth/2 + pad->GetClearance( NULL );
1146  pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
1147 
1148  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1149  {
1150  SEG textSeg( textShape[jj], textShape[jj+1] );
1151 
1152  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1153  {
1155  break;
1156  }
1157  }
1158  }
1159 }
1160 
1161 
1163 {
1165 
1167 
1168  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1169  {
1171  return;
1172  }
1173 }
1174 
1175 
1177 {
1179  wxCHECK( board, /*void*/ );
1180  LSET disabledLayers = board->GetEnabledLayers().flip();
1181 
1182  // Perform the test only for copper layers
1183  disabledLayers &= LSET::AllCuMask();
1184 
1185  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1187  aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1188  };
1189 
1190  for( auto track : board->Tracks() )
1191  {
1192  if( disabledLayers.test( track->GetLayer() ) )
1193  createMarker( track );
1194  }
1195 
1196  for( auto module : board->Modules() )
1197  {
1198  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1199  {
1200  if( disabledLayers.test( aItem->GetLayer() ) )
1201  createMarker( aItem );
1202  } );
1203  }
1204 
1205  for( auto zone : board->Zones() )
1206  {
1207  if( disabledLayers.test( zone->GetLayer() ) )
1208  createMarker( zone );
1209  }
1210 }
1211 
1212 
1213 bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit )
1214 {
1215  const static LSET all_cu = LSET::AllCuMask();
1216 
1217  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1218 
1219  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1220  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1221  * Therefore, this dummy pad is a circle or an oval.
1222  * A pad must have a parent because some functions expect a non null parent
1223  * to find the parent board, and some other data
1224  */
1225  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1226  D_PAD dummypad( &dummymodule );
1227 
1228  // Ensure the hole is on all copper layers
1229  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1230 
1231  // Use the minimal local clearance value for the dummy pad.
1232  // The clearance of the active pad will be used as minimum distance to a hole
1233  // (a value = 0 means use netclass value)
1234  dummypad.SetLocalClearance( 1 );
1235 
1236  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1237  {
1238  D_PAD* pad = *pad_list;
1239 
1240  if( pad == aRefPad )
1241  continue;
1242 
1243  // We can stop the test when pad->GetPosition().x > x_limit
1244  // because the list is sorted by X values
1245  if( pad->GetPosition().x > x_limit )
1246  break;
1247 
1248  // No problem if pads which are on copper layers are on different copper layers,
1249  // (pads can be only on a technical layer, to build complex pads)
1250  // but their hole (if any ) can create DRC error because they are on all
1251  // copper layers, so we test them
1252  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1253  ( pad->GetLayerSet() & all_cu ) != 0 &&
1254  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1255  {
1256  // if holes are in the same location and have the same size and shape,
1257  // this can be accepted
1258  if( pad->GetPosition() == aRefPad->GetPosition()
1259  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1260  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1261  {
1262  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1263  continue;
1264 
1265  // for oval holes: must also have the same orientation
1266  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1267  continue;
1268  }
1269 
1270  /* Here, we must test clearance between holes and pads
1271  * dummy pad size and shape is adjusted to pad drill size and shape
1272  */
1273  if( pad->GetDrillSize().x )
1274  {
1275  // pad under testing has a hole, test this hole against pad reference
1276  dummypad.SetPosition( pad->GetPosition() );
1277  dummypad.SetSize( pad->GetDrillSize() );
1278  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1280  dummypad.SetOrientation( pad->GetOrientation() );
1281 
1282  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1283  {
1284  // here we have a drc error on pad!
1286  return false;
1287  }
1288  }
1289 
1290  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1291  {
1292  dummypad.SetPosition( aRefPad->GetPosition() );
1293  dummypad.SetSize( aRefPad->GetDrillSize() );
1294  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1296  dummypad.SetOrientation( aRefPad->GetOrientation() );
1297 
1298  if( !checkClearancePadToPad( pad, &dummypad ) )
1299  {
1300  // here we have a drc error on aRefPad!
1302  return false;
1303  }
1304  }
1305 
1306  continue;
1307  }
1308 
1309  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1310  // But no problem if pads have the same netcode (same net)
1311  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1312  continue;
1313 
1314  // if pads are from the same footprint
1315  if( pad->GetParent() == aRefPad->GetParent() )
1316  {
1317  // and have the same pad number ( equivalent pads )
1318 
1319  // one can argue that this 2nd test is not necessary, that any
1320  // two pads from a single module are acceptable. This 2nd test
1321  // should eventually be a configuration option.
1322  if( pad->PadNameEqual( aRefPad ) )
1323  continue;
1324  }
1325 
1326  // if either pad has no drill and is only on technical layers, not a clearance violation
1327  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1328  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1329  {
1330  continue;
1331  }
1332 
1333  if( !checkClearancePadToPad( aRefPad, pad ) )
1334  {
1335  // here we have a drc error!
1337  return false;
1338  }
1339  }
1340 
1341  return true;
1342 }
1343 
1344 
1346 {
1347  DRC_COURTYARD_OVERLAP drc_overlap(
1348  m_markerFactory, [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1349 
1350  drc_overlap.RunDRC( *m_pcb );
1351 }
1352 
1353 
1354 void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS aUnits, DRC_LIST& aDRCList )
1355 {
1356 
1357  // Search for duplicate footprints on the board
1358  auto comp = []( const MODULE* x, const MODULE* y ) {
1359  return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
1360  };
1361  auto mods = std::set<MODULE*, decltype( comp )>( comp );
1362 
1363  for( auto mod : aPCB->Modules() )
1364  {
1365  auto ins = mods.insert( mod );
1366  if( !ins.second )
1367  {
1368  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_DUPLICATE_FOOTPRINT, mod,
1369  mod->GetPosition(), *ins.first, ( *ins.first )->GetPosition() ) );
1370  }
1371  }
1372 
1373  // Search for component footprints in the netlist but not on the board.
1374  for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
1375  {
1376  COMPONENT* component = aNetlist.GetComponent( ii );
1377 
1378  auto module = aPCB->FindModuleByReference( component->GetReference() );
1379 
1380  if( module == NULL )
1381  {
1382  wxString msg = wxString::Format( wxT( "%s (%s)" ),
1383  component->GetReference(),
1384  component->GetValue() );
1385 
1386  aDRCList.emplace_back( new DRC_ITEM( DRCE_MISSING_FOOTPRINT, msg ) );
1387  }
1388  }
1389 
1390  // Search for component footprints found on board but not in netlist.
1391  for( auto module : mods )
1392  {
1393  COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
1394 
1395  if( component == NULL )
1396  {
1397  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_EXTRA_FOOTPRINT,
1399  nullptr, wxPoint() ) );
1400  }
1401  }
1402 }
1403 
1404 
1406 {
1407  Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
1408 }
1409 
1410 
1411 
bool m_refillZones
Definition: drc.h:205
#define DRCE_EXTRA_FOOTPRINT
netlist item not found for footprint
Definition: drc.h:102
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
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:686
EDA_UNITS
Definition: common.h:72
#define DRCE_DISABLED_LAYER_ITEM
item on a disabled layer
Definition: drc.h:96
bool m_doCreateRptFile
Definition: drc.h:204
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
TEXTE_MODULE & Reference()
Definition: class_module.h:477
void DestroyDRCDialog(int aReason)
Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:239
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:202
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:662
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
TEXTE_PCB class definition.
DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
BOARD * board() const
void testCopperTextAndGraphics()
#define DRCE_PAD_NEAR_PAD1
pad too close to pad
Definition: drc.h:64
Model changes (required full reload)
Definition: tool_base.h:82
int TestZoneToZoneOutline(ZONE_CONTAINER *aZone, bool aCreateMarkers)
Tests whether distance between zones complies with the DRC rules.
int m_ycliplo
Definition: drc.h:232
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:77
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc.h:70
int GetX() const
Definition: eda_rect.h:111
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:243
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:791
STROKE_T GetShape() const
void setTransitions() override
Sets up handlers for various events.
bool IsVisible() const
Definition: eda_text.h:170
void testKeepoutAreas()
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:161
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
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...
int m_ycliphi
Definition: drc.h:234
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:204
int GetWidth() const
Definition: eda_rect.h:119
#define DRCE_DRILLED_HOLES_TOO_CLOSE
overlapping drilled holes break drill bits
Definition: drc.h:97
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:228
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:83
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:109
#define DRCE_MISSING_FOOTPRINT
footprint not found for netlist item
Definition: drc.h:100
int m_segmLength
Definition: drc.h:226
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:240
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:259
void ShowDRCDialog(wxWindow *aParent)
Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and create...
int GetThickness() const
Return the pen width.
Definition: eda_text.h:148
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:78
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
const std::vector< wxPoint > & GetBezierPoints() const
DRAWINGS & GraphicalItems()
Definition: class_module.h:183
#define DRCE_ZONES_INTERSECT
copper area outlines intersect
Definition: drc.h:67
#define FmtVal(x)
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:87
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc.h:47
const wxPoint GetPosition() const override
Definition: class_zone.cpp:198
bool doTrackDrc(TRACK *aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterator aEndIt, bool aTestZones)
Test the current segment.
DRCLISTBOX * m_UnconnectedListBox
void SetList(EDA_UNITS aUnits, DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
void testCopperTextItem(BOARD_ITEM *aTextItem)
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:251
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:650
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:69
Definitions for tracks, vias and zones.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:436
BOARD * m_pcb
Definition: drc.h:237
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:132
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:109
void testDrilledHoles()
void GetColinearCorners(BOARD *aBoard, std::set< VECTOR2I > &colinearCorners)
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:86
bool IsNetTie() const
Definition: class_module.h:267
#define DRCE_NETCLASS_uVIADRILLSIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc.h:82
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
#define DRCE_NETCLASS_VIASIZE
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc.h:79
bool m_testFootprints
Definition: drc.h:207
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
bool m_doKeepoutTest
Definition: drc.h:203
ZONE_FILLER_TOOL.
int m_HoleToHoleMin
Min width of peninsula between two drilled holes.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:948
LSET is a set of PCB_LAYER_IDs.
bool m_doZonesTest
Definition: drc.h:202
iterator begin()
Definition: netclass.h:248
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:101
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:217
#define NULL
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:226
void testZones()
SHAPE_POLY_SET.
DRCLISTBOX * m_ClearanceListBox
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:476
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, std::set< VECTOR2I > *aPreserveCorners) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly.
DRC_LIST_MARKERS is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD instanc...
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false, int aMarkupFlags=0) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:184
int m_TrackMinWidth
track min value for width ((min copper size value
const wxPoint GetPosition() const
Definition: eda_rect.h:115
Arcs (with rounded ends)
int m_ViasMinSize
vias (not micro vias) min diameter
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:428
TOOL_EVENT.
Definition: tool_event.h:171
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:442
DRC_LIST_GENERIC is an implementation of the interface named DRC_ITEM_LIST which uses a vector of poi...
const wxString & GetReference() const
Definition: pcb_netlist.h:154
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:300
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.
Definition: eda_text.cpp:544
void SetSize(const wxSize &aSize)
Definition: class_pad.h:299
#define DRCE_INVALID_OUTLINE
invalid board outline
Definition: drc.h:99
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).
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:206
std::vector< DRC_ITEM * > DRC_LIST
Definition: drc.h:175
Bezier Curve.
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:80
bool m_drcRun
Definition: drc.h:244
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
bool doPadToPadsDrc(D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Test the clearance between aRefPad and other pads.
int m_xcliphi
Definition: drc.h:233
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:236
const wxPoint GetPosition() const override
Definition: class_track.h:309
bool m_doPad2PadTest
Definition: drc.h:200
void testPad2Pad()
int GetHeight() const
Definition: eda_rect.h:120
bool Show(bool show) override
int GetWidth() const
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:631
Pad object description.
void SetLocalClearance(int aClearance)
Definition: class_pad.h:461
A class that provides the courtyard-based DRC checks.
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:85
bool m_footprintsTested
Definition: drc.h:245
friend class DIALOG_DRC_CONTROL
Definition: drc.h:188
MODULE * GetParent() const
Definition: class_pad.h:167
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:211
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:268
Definition: seg.h:39
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
double GetAngle() const
bool m_RequireCourtyards
require courtyard definitions in footprints
void SetLayerSet(LSET aLayerMask)
Definition: class_pad.h:441
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:238
ZONE_CONTAINERS & Zones()
Definition: class_board.h:240
bool testNetClasses()
Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance ...
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
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:101
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:100
wxString m_rptFilename
Definition: drc.h:209
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
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:160
MODULE * module() const
#define _(s)
Definition: 3d_actions.cpp:31
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:422
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
DRCLISTBOX * m_FootprintsListBox
const wxSize & GetDrillSize() const
Definition: class_pad.h:306
VECTOR2I A
Definition: seg.h:47
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc.h:84
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:68
VIATYPE GetViaType() const
Definition: class_track.h:336
static TOOL_ACTION runDRC
Definition: pcb_actions.h:322
int GetY() const
Definition: eda_rect.h:112
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
#define DRCE_PAD_NEAR_COPPER
pad and copper graphic collide or are too close
Definition: drc.h:88
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596
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:238
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:438
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void Activate()
Function Activate() Runs the tool.
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:268
const wxString & GetValue() const
Definition: pcb_netlist.h:156
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:97
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
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:913
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:240
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:242
const wxPoint GetPosition() const override
Definition: class_pad.h:241
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
void testUnconnected()
void RunTests(wxTextCtrl *aMessages=NULL)
Run all the tests specified with a previous call to SetSettings()
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:247
int m_xcliplo
Definition: drc.h:231
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:210
DRAWINGS & Drawings()
Definition: class_board.h:235
#define DRCE_NETCLASS_uVIASIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc.h:81
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
TRACKS & Tracks()
Definition: class_board.h:217
bool m_doUnconnectedTest
Definition: drc.h:201
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:210
double m_segmAngle
Definition: drc.h:225
static void TestFootprints(NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS aUnits, DRC_LIST &aDRCList)
Test the board footprints against a netlist.
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
void doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:154
std::list< ZONE_CONTAINER * > GetZoneList(bool aIncludeZonesInFootprints=false)
Function GetZoneList.
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
VECTOR2I B
Definition: seg.h:48