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>
51 #include <pcb_netlist.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  // Test keepout areas for vias, tracks and pads inside keepout areas
886  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
887  {
888  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
889 
890  if( !area->GetIsKeepout() )
891  continue;
892 
893  for( auto segm : m_pcb->Tracks() )
894  {
895  if( segm->Type() == PCB_TRACE_T )
896  {
897  if( !area->GetDoNotAllowTracks() )
898  continue;
899 
900  // Ignore if the keepout zone is not on the same layer
901  if( !area->IsOnLayer( segm->GetLayer() ) )
902  continue;
903 
904  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
905 
906  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
909  }
910  else if( segm->Type() == PCB_VIA_T )
911  {
912  if( ! area->GetDoNotAllowVias() )
913  continue;
914 
915  auto viaLayers = segm->GetLayerSet();
916 
917  if( !area->CommonLayerExists( viaLayers ) )
918  continue;
919 
920  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
923  }
924  }
925  // Test pads: TODO
926  }
927 }
928 
929 
931 {
932  // Test copper items for clearance violations with vias, tracks and pads
933 
934  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
935  {
936  if( IsCopperLayer( brdItem->GetLayer() ) )
937  {
938  if( brdItem->Type() == PCB_TEXT_T )
939  testCopperTextItem( brdItem );
940  else if( brdItem->Type() == PCB_LINE_T )
941  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
942  }
943  }
944 
945  for( MODULE* module : m_pcb->Modules() )
946  {
947  TEXTE_MODULE& ref = module->Reference();
948  TEXTE_MODULE& val = module->Value();
949 
950  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
951  testCopperTextItem( &ref );
952 
953  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
954  testCopperTextItem( &val );
955 
956  if( module->IsNetTie() )
957  continue;
958 
959  for( auto item : module->GraphicalItems() )
960  {
961  if( IsCopperLayer( item->GetLayer() ) )
962  {
963  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
964  testCopperTextItem( item );
965  else if( item->Type() == PCB_MODULE_EDGE_T )
966  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
967  }
968  }
969  }
970 }
971 
972 
974 {
975  std::vector<SEG> itemShape;
976  int itemWidth = aItem->GetWidth();
977 
978  switch( aItem->GetShape() )
979  {
980  case S_ARC:
981  {
982  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
983 
984  auto l = arc.ConvertToPolyline();
985 
986  for( int i = 0; i < l.SegmentCount(); i++ )
987  itemShape.push_back( l.CSegment(i) );
988 
989  break;
990  }
991 
992  case S_SEGMENT:
993  itemShape.emplace_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
994  break;
995 
996  case S_CIRCLE:
997  {
998  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
999  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1000 
1001  auto l = circle.ConvertToPolyline();
1002 
1003  for( int i = 0; i < l.SegmentCount(); i++ )
1004  itemShape.push_back( l.CSegment(i) );
1005 
1006  break;
1007  }
1008 
1009  case S_CURVE:
1010  {
1011  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1012  wxPoint start_pt = aItem->GetBezierPoints()[0];
1013 
1014  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1015  {
1016  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1017  itemShape.emplace_back( SEG( start_pt, end_pt ) );
1018  start_pt = end_pt;
1019  }
1020 
1021  break;
1022  }
1023 
1024  default:
1025  break;
1026  }
1027 
1028  // Test tracks and vias
1029  for( auto track : m_pcb->Tracks() )
1030  {
1031  if( !track->IsOnLayer( aItem->GetLayer() ) )
1032  continue;
1033 
1034  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1035  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1036 
1037  for( const auto& itemSeg : itemShape )
1038  {
1039  if( trackAsSeg.Distance( itemSeg ) < minDist )
1040  {
1041  if( track->Type() == PCB_VIA_T )
1043  track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1044  else
1046  track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1047  break;
1048  }
1049  }
1050  }
1051 
1052  // Test pads
1053  for( auto pad : m_pcb->GetPads() )
1054  {
1055  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1056  continue;
1057 
1058  // Graphic items are allowed to act as net-ties within their own footprint
1059  if( pad->GetParent() == aItem->GetParent() )
1060  continue;
1061 
1062  SHAPE_POLY_SET padOutline;
1063  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ) );
1064 
1065  for( const auto& itemSeg : itemShape )
1066  {
1067  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1068  {
1070  break;
1071  }
1072  }
1073  }
1074 }
1075 
1076 
1078 {
1079  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1080 
1081  if( text == nullptr )
1082  return;
1083 
1084  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1085  int textWidth = text->GetThickness();
1086 
1087  // So far the bounding box makes up the text-area
1088  text->TransformTextShapeToSegmentList( textShape );
1089 
1090  if( textShape.size() == 0 ) // Should not happen (empty text?)
1091  return;
1092 
1093  EDA_RECT bbox = text->GetTextBox();
1094  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1095 
1096  // Test tracks and vias
1097  for( auto track : m_pcb->Tracks() )
1098  {
1099  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1100  continue;
1101 
1102  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1103  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1104 
1105  // Fast test to detect a trach segment candidate inside the text bounding box
1106  if( !rect_area.Collide( trackAsSeg, minDist ) )
1107  continue;
1108 
1109  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1110  {
1111  SEG textSeg( textShape[jj], textShape[jj+1] );
1112 
1113  if( trackAsSeg.Distance( textSeg ) < minDist )
1114  {
1115  if( track->Type() == PCB_VIA_T )
1117  track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1118  else
1120  track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
1121  break;
1122  }
1123  }
1124  }
1125 
1126  // Test pads
1127  for( auto pad : m_pcb->GetPads() )
1128  {
1129  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1130  continue;
1131 
1132  // Fast test to detect a pad candidate inside the text bounding box
1133  // Finer test (time consumming) is made only for pads near the text.
1134  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1135  VECTOR2I shape_pos( pad->ShapePos() );
1136 
1137  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1138  continue;
1139 
1140  SHAPE_POLY_SET padOutline;
1141 
1142  int minDist = textWidth/2 + pad->GetClearance( NULL );
1143  pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
1144 
1145  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1146  {
1147  SEG textSeg( textShape[jj], textShape[jj+1] );
1148 
1149  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1150  {
1152  break;
1153  }
1154  }
1155  }
1156 }
1157 
1158 
1160 {
1161  wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
1162 
1164 
1165  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1166  {
1168  return;
1169  }
1170 }
1171 
1172 
1174 {
1176  wxCHECK( board, /*void*/ );
1177  LSET disabledLayers = board->GetEnabledLayers().flip();
1178 
1179  // Perform the test only for copper layers
1180  disabledLayers &= LSET::AllCuMask();
1181 
1182  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1184  aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1185  };
1186 
1187  for( auto track : board->Tracks() )
1188  {
1189  if( disabledLayers.test( track->GetLayer() ) )
1190  createMarker( track );
1191  }
1192 
1193  for( auto module : board->Modules() )
1194  {
1195  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1196  {
1197  if( disabledLayers.test( aItem->GetLayer() ) )
1198  createMarker( aItem );
1199  } );
1200  }
1201 
1202  for( auto zone : board->Zones() )
1203  {
1204  if( disabledLayers.test( zone->GetLayer() ) )
1205  createMarker( zone );
1206  }
1207 }
1208 
1209 
1210 bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_limit )
1211 {
1212  const static LSET all_cu = LSET::AllCuMask();
1213 
1214  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1215 
1216  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1217  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1218  * Therefore, this dummy pad is a circle or an oval.
1219  * A pad must have a parent because some functions expect a non null parent
1220  * to find the parent board, and some other data
1221  */
1222  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1223  D_PAD dummypad( &dummymodule );
1224 
1225  // Ensure the hole is on all copper layers
1226  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1227 
1228  // Use the minimal local clearance value for the dummy pad.
1229  // The clearance of the active pad will be used as minimum distance to a hole
1230  // (a value = 0 means use netclass value)
1231  dummypad.SetLocalClearance( 1 );
1232 
1233  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1234  {
1235  D_PAD* pad = *pad_list;
1236 
1237  if( pad == aRefPad )
1238  continue;
1239 
1240  // We can stop the test when pad->GetPosition().x > x_limit
1241  // because the list is sorted by X values
1242  if( pad->GetPosition().x > x_limit )
1243  break;
1244 
1245  // No problem if pads which are on copper layers are on different copper layers,
1246  // (pads can be only on a technical layer, to build complex pads)
1247  // but their hole (if any ) can create DRC error because they are on all
1248  // copper layers, so we test them
1249  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1250  ( pad->GetLayerSet() & all_cu ) != 0 &&
1251  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1252  {
1253  // if holes are in the same location and have the same size and shape,
1254  // this can be accepted
1255  if( pad->GetPosition() == aRefPad->GetPosition()
1256  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1257  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1258  {
1259  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1260  continue;
1261 
1262  // for oval holes: must also have the same orientation
1263  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1264  continue;
1265  }
1266 
1267  /* Here, we must test clearance between holes and pads
1268  * dummy pad size and shape is adjusted to pad drill size and shape
1269  */
1270  if( pad->GetDrillSize().x )
1271  {
1272  // pad under testing has a hole, test this hole against pad reference
1273  dummypad.SetPosition( pad->GetPosition() );
1274  dummypad.SetSize( pad->GetDrillSize() );
1275  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1277  dummypad.SetOrientation( pad->GetOrientation() );
1278 
1279  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1280  {
1281  // here we have a drc error on pad!
1283  return false;
1284  }
1285  }
1286 
1287  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1288  {
1289  dummypad.SetPosition( aRefPad->GetPosition() );
1290  dummypad.SetSize( aRefPad->GetDrillSize() );
1291  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1293  dummypad.SetOrientation( aRefPad->GetOrientation() );
1294 
1295  if( !checkClearancePadToPad( pad, &dummypad ) )
1296  {
1297  // here we have a drc error on aRefPad!
1299  return false;
1300  }
1301  }
1302 
1303  continue;
1304  }
1305 
1306  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1307  // But no problem if pads have the same netcode (same net)
1308  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1309  continue;
1310 
1311  // if pads are from the same footprint
1312  if( pad->GetParent() == aRefPad->GetParent() )
1313  {
1314  // and have the same pad number ( equivalent pads )
1315 
1316  // one can argue that this 2nd test is not necessary, that any
1317  // two pads from a single module are acceptable. This 2nd test
1318  // should eventually be a configuration option.
1319  if( pad->PadNameEqual( aRefPad ) )
1320  continue;
1321  }
1322 
1323  // if either pad has no drill and is only on technical layers, not a clearance violation
1324  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1325  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1326  {
1327  continue;
1328  }
1329 
1330  if( !checkClearancePadToPad( aRefPad, pad ) )
1331  {
1332  // here we have a drc error!
1334  return false;
1335  }
1336  }
1337 
1338  return true;
1339 }
1340 
1341 
1343 {
1344  DRC_COURTYARD_OVERLAP drc_overlap(
1345  m_markerFactory, [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1346 
1347  drc_overlap.RunDRC( *m_pcb );
1348 }
1349 
1350 
1351 void DRC::TestFootprints( NETLIST& aNetlist, BOARD* aPCB, EDA_UNITS_T aUnits,
1352  DRC_LIST& aDRCList )
1353 {
1354 
1355  // Search for duplicate footprints on the board
1356  auto comp = []( const MODULE* x, const MODULE* y ) {
1357  return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
1358  };
1359  auto mods = std::set<MODULE*, decltype( comp )>( comp );
1360 
1361  for( auto mod : aPCB->Modules() )
1362  {
1363  auto ins = mods.insert( mod );
1364  if( !ins.second )
1365  {
1366  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_DUPLICATE_FOOTPRINT, mod,
1367  mod->GetPosition(), *ins.first, ( *ins.first )->GetPosition() ) );
1368  }
1369  }
1370 
1371  // Search for component footprints in the netlist but not on the board.
1372  for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
1373  {
1374  COMPONENT* component = aNetlist.GetComponent( ii );
1375 
1376  auto module = aPCB->FindModuleByReference( component->GetReference() );
1377 
1378  if( module == NULL )
1379  {
1380  wxString msg = wxString::Format( wxT( "%s (%s)" ),
1381  component->GetReference(),
1382  component->GetValue() );
1383 
1384  aDRCList.emplace_back( new DRC_ITEM( DRCE_MISSING_FOOTPRINT, msg ) );
1385  }
1386  }
1387 
1388  // Search for component footprints found on board but not in netlist.
1389  for( auto module : mods )
1390  {
1391  COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
1392 
1393  if( component == NULL )
1394  {
1395  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_EXTRA_FOOTPRINT,
1397  nullptr, wxPoint() ) );
1398  }
1399  }
1400 }
1401 
1402 
1404 {
1405  Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
1406 }
1407 
1408 
1409 
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:57
TEXTE_MODULE & Reference()
Definition: class_module.h:448
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:690
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
TEXTE_PCB class definition.
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set.
Definition: class_zone.cpp:197
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:930
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:115
#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:109
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
DRC_LIST m_footprints
list of footprint warnings, as DRC_ITEMs
Definition: drc.h: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:804
STROKE_T GetShape() const
void setTransitions() override
Sets up handlers for various events.
Definition: drc.cpp:1403
bool IsVisible() const
Definition: eda_text.h:170
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_zone.cpp:267
void testKeepoutAreas()
Definition: drc.cpp:883
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:200
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:178
int GetWidth() const
Definition: eda_rect.h:117
#define DRCE_DRILLED_HOLES_TOO_CLOSE
overlapping drilled holes break drill bits
Definition: drc.h:97
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:237
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:973
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:540
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:173
#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:1159
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:172
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:1077
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:616
#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:95
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:407
BOARD * m_pcb
Definition: drc.h:237
bool GetDoNotAllowVias() const
Definition: class_zone.h:623
static void TestFootprints(NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS_T aUnits, DRC_LIST &aDRCList)
Test the board footprints against a netlist.
Definition: drc.cpp:1351
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:238
#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:955
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
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false) const
Function GetTextBox useful in multiline texts to calculate the full text or a line area (for zones fi...
Definition: eda_text.cpp:178
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:236
void testZones()
Definition: drc.cpp:847
Class SHAPE_POLY_SET.
DRCLISTBOX * m_ClearanceListBox
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:447
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...
int m_TrackMinWidth
track min value for width ((min copper size value
const wxPoint GetPosition() const
Definition: eda_rect.h:113
Arcs (with rounded ends)
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:168
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:310
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:538
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:1173
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:1210
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:118
bool Show(bool show) override
int GetWidth() const
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:621
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:250
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:94
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:597
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:323
int GetY() const
Definition: eda_rect.h:110
#define DRCE_PAD_NEAR_COPPER
pad and copper graphic collide or are too close
Definition: drc.h: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 GetDoNotAllowTracks() const
Definition: class_zone.h:624
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:96
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:926
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:188
DRAWINGS & Drawings()
Definition: class_board.h:245
#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:154
TRACKS & Tracks()
Definition: class_board.h:227
bool m_doUnconnectedTest
Definition: drc.h:201
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:184
double m_segmAngle
Definition: drc.h:225
void doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1342
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:193
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
VECTOR2I B
Definition: seg.h:45