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