KiCad PCB EDA Suite
pcbnew/drc/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-2020 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 <geometry/seg.h>
38 #include <math_for_graphics.h>
40 #include <bitmaps.h>
41 #include <tool/tool_manager.h>
42 #include <tools/pcb_actions.h>
43 #include <tools/pcb_tool_base.h>
44 #include <tools/zone_filler_tool.h>
45 #include <kiface_i.h>
46 #include <pcbnew.h>
48 #include <math/util.h> // for KiROUND
49 #include <dialog_drc.h>
50 #include <wx/progdlg.h>
51 #include <board_commit.h>
52 #include <geometry/shape_segment.h>
53 #include <geometry/shape_arc.h>
54 #include <drc/drc.h>
55 #include <drc/drc_rule_parser.h>
56 #include <drc/drc_item.h>
59 #include <drc/drc_keepout_tester.h>
60 #include <drc/drc_textvar_tester.h>
61 #include <drc/footprint_tester.h>
63 #include <reporter.h>
64 
66  PCB_TOOL_BASE( "pcbnew.DRCTool" ),
67  m_editFrame( nullptr ),
68  m_pcb( nullptr ),
69  m_board_outline_valid( false ),
70  m_drcDialog( nullptr ),
72 {
73  // establish initial values for everything:
74  m_doUnconnectedTest = true; // enable unconnected tests
75  m_testTracksAgainstZones = false; // disable zone to items clearance tests
76  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
77  m_refillZones = false; // Only fill zones if requested by user.
78  m_reportAllTrackErrors = false;
79  m_testFootprints = false;
80 
81  m_drcRun = false;
82  m_footprintsTested = false;
83 }
84 
85 
87 {
88  for( DRC_ITEM* unconnectedItem : m_unconnected )
89  delete unconnectedItem;
90 
91  for( DRC_ITEM* footprintItem : m_footprints )
92  delete footprintItem;
93 }
94 
95 
96 void DRC::Reset( RESET_REASON aReason )
97 {
98  m_editFrame = getEditFrame<PCB_EDIT_FRAME>();
99 
100  if( m_pcb != m_editFrame->GetBoard() )
101  {
102  if( m_drcDialog )
103  DestroyDRCDialog( wxID_OK );
104 
106  }
107 }
108 
109 
110 void DRC::ShowDRCDialog( wxWindow* aParent )
111 {
112  bool show_dlg_modal = true;
113 
114  // the dialog needs a parent frame. if it is not specified, this is
115  // the PCB editor frame specified in DRC class.
116  if( !aParent )
117  {
118  // if any parent is specified, the dialog is modal.
119  // if this is the default PCB editor frame, it is not modal
120  show_dlg_modal = false;
121  aParent = m_editFrame;
122  }
123 
124  Activate();
126 
127  if( !m_drcDialog )
128  {
129  m_drcDialog = new DIALOG_DRC( this, m_editFrame, aParent );
130  updatePointers();
131 
132  if( show_dlg_modal )
133  m_drcDialog->ShowModal();
134  else
135  m_drcDialog->Show( true );
136  }
137  else // The dialog is just not visible (because the user has double clicked on an error item)
138  {
139  updatePointers();
140  m_drcDialog->Show( true );
141  }
142 }
143 
144 
145 int DRC::ShowDRCDialog( const TOOL_EVENT& aEvent )
146 {
147  ShowDRCDialog( nullptr );
148  return 0;
149 }
150 
151 
153 {
154  if( m_drcDialog )
155  return m_drcDialog->IsShown();
156 
157  return false;
158 }
159 
160 
161 void DRC::addMarkerToPcb( BOARD_COMMIT& aCommit, MARKER_PCB* aMarker )
162 {
163  if( m_pcb->GetDesignSettings().Ignore( aMarker->GetRCItem()->GetErrorCode() ) )
164  {
165  delete aMarker;
166  return;
167  }
168 
169  aCommit.Add( aMarker );
170 }
171 
172 
173 void DRC::DestroyDRCDialog( int aReason )
174 {
175  if( m_drcDialog )
176  {
177  m_drcDialog->Destroy();
178  m_drcDialog = nullptr;
179  }
180 }
181 
182 
184 {
185  wxString rulesFilepath = m_editFrame->Prj().AbsolutePath( "drc-rules" );
186  wxFileName rulesFile( rulesFilepath );
187 
188  if( rulesFile.FileExists() )
189  {
190  m_rules.clear();
191 
192  FILE* fp = wxFopen( rulesFilepath, wxT( "rt" ) );
193 
194  if( fp )
195  {
196  try
197  {
198  DRC_RULES_PARSER parser( m_pcb, fp, rulesFilepath );
200  }
201  catch( PARSE_ERROR& pe )
202  {
203  // Don't leave possibly malformed stuff around for us to trip over
204  m_rules.clear();
205 
206  wxSafeYield( m_editFrame );
208  pe.lineNumber, pe.byteIndex );
209 
210  return false;
211  }
212  }
213  }
214 
215  std::reverse( std::begin( m_rules ), std::end( m_rules ) );
216 
218  bds.m_DRCRules = m_rules;
219 
220  return true;
221 }
222 
223 
224 void DRC::RunTests( wxTextCtrl* aMessages )
225 {
226  // Make absolutely sure these are up-to-date
227  if( !LoadRules() )
228  return;
229 
230  wxASSERT( m_pcb == m_editFrame->GetBoard() );
231 
232  BOARD_COMMIT commit( m_editFrame );
234 
236 
237  if( !bds.Ignore( DRCE_INVALID_OUTLINE )
239  {
240  if( aMessages )
241  {
242  aMessages->AppendText( _( "Board Outline...\n" ) );
243  wxSafeYield();
244  }
245 
246  testOutline( commit );
247  }
248 
249  // test pad to pad clearances, nothing to do with tracks, vias or zones.
250  if( !bds.Ignore( DRCE_COPPER_EDGE_CLEARANCE ) )
251  {
252  if( aMessages )
253  {
254  aMessages->AppendText( _( "Pad clearances...\n" ) );
255  wxSafeYield();
256  }
257 
258  testPadClearances( commit );
259  }
260 
261  // test drilled holes
263  || !bds.Ignore( DRCE_TOO_SMALL_DRILL )
265  {
266  if( aMessages )
267  {
268  aMessages->AppendText( _( "Drill sizes and clearances...\n" ) );
269  wxSafeYield();
270  }
271 
272  DRC_DRILLED_HOLE_TESTER tester( [&]( MARKER_PCB* aMarker )
273  {
274  addMarkerToPcb( commit, aMarker );
275  } );
276 
277  tester.RunDRC( userUnits(), *m_pcb );
278  }
279 
280  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
281  wxWindow* caller = aMessages ? aMessages->GetParent() : m_editFrame;
282 
283  if( m_refillZones )
284  {
285  if( aMessages )
286  aMessages->AppendText( _( "Refilling all zones...\n" ) );
287 
288  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->FillAllZones( caller );
289  }
290  else
291  {
292  if( aMessages )
293  aMessages->AppendText( _( "Checking zone fills...\n" ) );
294 
295  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( caller );
296  }
297 
298  // test track and via clearances to other tracks, pads, and vias
299  if( aMessages )
300  {
301  aMessages->AppendText( _( "Track clearances...\n" ) );
302  wxSafeYield();
303  }
304 
305  testTracks( commit, aMessages ? aMessages->GetParent() : m_editFrame, true );
306 
307  // test zone clearances to other zones
308  if( aMessages )
309  {
310  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
311  wxSafeYield();
312  }
313 
314  testZones( commit );
315 
316  // find and gather unconnected pads.
318  && !bds.Ignore( DRCE_UNCONNECTED_ITEMS ) )
319  {
320  if( aMessages )
321  {
322  aMessages->AppendText( _( "Unconnected pads...\n" ) );
323  aMessages->Refresh();
324  }
325 
326  testUnconnected();
327  }
328 
329  // find and gather vias, tracks, pads inside keepout areas.
330  if( m_doKeepoutTest )
331  {
332  if( aMessages )
333  {
334  aMessages->AppendText( _( "Keepout areas ...\n" ) );
335  aMessages->Refresh();
336  }
337 
338  DRC_KEEPOUT_TESTER tester( [&]( MARKER_PCB* aMarker )
339  {
340  addMarkerToPcb( commit, aMarker );
341  } );
342 
343  tester.RunDRC( userUnits(), *m_pcb );
344  }
345 
346  // find and gather vias, tracks, pads inside text boxes.
347  if( !bds.Ignore( DRCE_CLEARANCE ) )
348  {
349  if( aMessages )
350  {
351  aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
352  wxSafeYield();
353  }
354 
355  testCopperTextAndGraphics( commit );
356  }
357 
358  // test courtyards
360  || !bds.Ignore( DRCE_MISSING_COURTYARD )
362  || !bds.Ignore( DRCE_PTH_IN_COURTYARD )
363  || !bds.Ignore( DRCE_NPTH_IN_COURTYARD ) )
364  {
365  if( aMessages )
366  {
367  aMessages->AppendText( _( "Courtyard areas...\n" ) );
368  aMessages->Refresh();
369  }
370 
371  DRC_COURTYARD_TESTER tester( [&]( MARKER_PCB* aMarker )
372  {
373  addMarkerToPcb( commit, aMarker );
374  } );
375 
376  tester.RunDRC( userUnits(), *m_pcb );
377  }
378 
379  for( DRC_ITEM* footprintItem : m_footprints )
380  delete footprintItem;
381 
382  m_footprints.clear();
383  m_footprintsTested = false;
384 
385  if( m_testFootprints && !Kiface().IsSingle() )
386  {
387  if( aMessages )
388  {
389  aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
390  aMessages->Refresh();
391  }
392 
393  NETLIST netlist;
395 
396  if( m_drcDialog )
397  m_drcDialog->Raise();
398 
399  TestFootprints( netlist, m_pcb, m_footprints );
400  m_footprintsTested = true;
401  }
402 
403  // Check if there are items on disabled layers
404  if( !bds.Ignore( DRCE_DISABLED_LAYER_ITEM ) )
405  {
406  if( aMessages )
407  {
408  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
409  aMessages->Refresh();
410  }
411 
412  testDisabledLayers( commit );
413  }
414 
415  if( !bds.Ignore( DRCE_UNRESOLVED_VARIABLE ) )
416  {
417  if( aMessages )
418  {
419  aMessages->AppendText( _( "Unresolved text variables...\n" ) );
420  aMessages->Refresh();
421  }
422 
423  DRC_TEXTVAR_TESTER tester( [&]( MARKER_PCB* aMarker )
424  {
425  addMarkerToPcb( commit, aMarker );
426  },
428 
429  tester.RunDRC( userUnits(), *m_pcb );
430  }
431 
432  commit.Push( wxEmptyString, false, false );
433  m_drcRun = true;
434 
435  // update the m_drcDialog listboxes
436  updatePointers();
437 
438  if( aMessages )
439  {
440  // no newline on this one because it is last, don't want the window
441  // to unnecessarily scroll.
442  aMessages->AppendText( _( "Finished" ) );
443  }
444 }
445 
446 
448 {
449  // update my pointers, m_editFrame is the only unchangeable one
451 
453 
454  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
455  {
458  &m_unconnected ) );
460  &m_footprints ) );
461  }
462 }
463 
464 
466 {
468  std::vector<D_PAD*> sortedPads;
469 
470  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
471 
472  if( sortedPads.empty() )
473  return;
474 
475  // find the max size of the pads (used to stop the pad-to-pad tests)
476  int max_size = 0;
477 
478  for( D_PAD* pad : sortedPads )
479  {
480  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
481  int radius = pad->GetBoundingRadius();
482 
483  if( radius > max_size )
484  max_size = radius;
485  }
486 
487  // Better to be fast than accurate; this keeps us from having to look up / calculate the
488  // actual clearances
489  max_size += m_largestClearance;
490 
491  // Upper limit of pad list (limit not included)
492  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
493 
494  // Test the pads
495  for( auto& pad : sortedPads )
496  {
498  {
499  int minClearance = bds.m_CopperEdgeClearance;
500  m_clearanceSource = _( "board edge" );
501 
502  static DRAWSEGMENT dummyEdge;
503  dummyEdge.SetLayer( Edge_Cuts );
504 
505  pad->GetRuleClearance( &dummyEdge, pad->GetLayer(), &minClearance, &m_clearanceSource );
506 
507  for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
508  {
509  SHAPE_SEGMENT edge( *it );
510  int actual;
511 
512  if( pad->Collide( &edge, minClearance, &actual ) )
513  {
515 
516  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
518  MessageTextFromValue( userUnits(), minClearance, true ),
519  MessageTextFromValue( userUnits(), actual, true ) );
520 
521  drcItem->SetErrorMessage( m_msg );
522  drcItem->SetItems( pad );
523 
524  MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
525  addMarkerToPcb( aCommit, marker );
526 
527  break;
528  }
529  }
530  }
531 
532  if( !bds.Ignore( DRCE_CLEARANCE ) )
533  {
534  int x_limit = pad->GetPosition().x + pad->GetBoundingRadius() + max_size;
535 
536  doPadToPadsDrc( aCommit, pad, &pad, listEnd, x_limit );
537  }
538  }
539 }
540 
541 
542 void DRC::testTracks( BOARD_COMMIT& aCommit, wxWindow *aActiveWindow, bool aShowProgressBar )
543 {
544  wxProgressDialog* progressDialog = NULL;
545  const int delta = 500; // This is the number of tests between 2 calls to the
546  // progress bar
547  int count = m_pcb->Tracks().size();
548  int deltamax = count/delta;
549 
550  if( aShowProgressBar && deltamax > 3 )
551  {
552  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
553  // on OSX
554  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
555  deltamax, aActiveWindow,
556  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
557  progressDialog->Update( 0, wxEmptyString );
558  }
559 
560  std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_pcb->GetConnectivity();
562 
563 
566  {
567  connectivity->Clear();
568  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
569  }
570 
571  int ii = 0;
572  count = 0;
573 
574  for( auto seg_it = m_pcb->Tracks().begin(); seg_it != m_pcb->Tracks().end(); seg_it++ )
575  {
576  if( ii++ > delta )
577  {
578  ii = 0;
579  count++;
580 
581  if( progressDialog )
582  {
583  if( !progressDialog->Update( count, wxEmptyString ) )
584  break; // Aborted by user
585 #ifdef __WXMAC__
586  // Work around a dialog z-order issue on OS X
587  if( count == deltamax )
588  aActiveWindow->Raise();
589 #endif
590  }
591  }
592 
593  // Test new segment against tracks and pads, optionally against copper zones
594  doTrackDrc( aCommit, *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_testTracksAgainstZones );
595 
596  // Test for dangling items
597  int code = (*seg_it)->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK;
598  wxPoint pos;
599 
600  if( !settings.Ignore( code ) && connectivity->TestTrackEndpointDangling( *seg_it, &pos ) )
601  {
602  DRC_ITEM* drcItem = DRC_ITEM::Create( code );
603  drcItem->SetItems( *seg_it );
604 
605  MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
606  addMarkerToPcb( aCommit, marker );
607  }
608  }
609 
610  if( progressDialog )
611  progressDialog->Destroy();
612 }
613 
614 
616 {
617  for( DRC_ITEM* unconnectedItem : m_unconnected )
618  delete unconnectedItem;
619 
620  m_unconnected.clear();
621 
622  auto connectivity = m_pcb->GetConnectivity();
623 
624  connectivity->Clear();
625  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
626  connectivity->RecalculateRatsnest();
627 
628  std::vector<CN_EDGE> edges;
629  connectivity->GetUnconnectedEdges( edges );
630 
631  for( const CN_EDGE& edge : edges )
632  {
634  item->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() );
635  m_unconnected.push_back( item );
636  }
637 }
638 
639 
640 void DRC::testZones( BOARD_COMMIT& aCommit )
641 {
643 
644  // Test copper areas for valid netcodes
645  // if a netcode is < 0 the netname was not found when reading a netlist
646  // if a netcode is == 0 the netname is void, and the zone is not connected.
647  // This is allowed, but i am not sure this is a good idea
648  //
649  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
650  // is stored, and initialized from the file or the zone properties editor.
651  // if it differs from the net name from net code, there is a DRC issue
652 
653  std::vector<SHAPE_POLY_SET> smoothed_polys;
654  smoothed_polys.resize( m_pcb->GetAreaCount() );
655 
656  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
657  {
658  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
659 
660  if( !bds.Ignore( DRCE_ZONE_HAS_EMPTY_NET ) && zone->IsOnCopperLayer() )
661  {
662  int netcode = zone->GetNetCode();
663  // a netcode < 0 or > 0 and no pad in net is a error or strange
664  // perhaps a "dead" net, which happens when all pads in this net were removed
665  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
666  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
667 
668  if( ( netcode < 0 ) || pads_in_net == 0 )
669  {
671  drcItem->SetItems( zone );
672 
673  MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() );
674  addMarkerToPcb( aCommit, marker );
675  }
676  }
677 
678  ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ii );
679  std::set<VECTOR2I> colinearCorners;
680  zoneRef->GetColinearCorners( m_pcb, colinearCorners );
681 
682  zoneRef->BuildSmoothedPoly( smoothed_polys[ii], &colinearCorners );
683  }
684 
685  // iterate through all areas
686  for( int ia = 0; ia < m_pcb->GetAreaCount(); ia++ )
687  {
688  ZONE_CONTAINER* zoneRef = m_pcb->GetArea( ia );
689 
690  if( !zoneRef->IsOnCopperLayer() )
691  continue;
692 
693  // If we are testing a single zone, then iterate through all other zones
694  // Otherwise, we have already tested the zone combination
695  for( int ia2 = ia + 1; ia2 < m_pcb->GetAreaCount(); ia2++ )
696  {
697  ZONE_CONTAINER* zoneToTest = m_pcb->GetArea( ia2 );
698 
699  if( zoneRef == zoneToTest )
700  continue;
701 
702  // test for same layer
703  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
704  continue;
705 
706  // Test for same net
707  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
708  continue;
709 
710  // test for different priorities
711  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
712  continue;
713 
714  // test for different types
715  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
716  continue;
717 
718  // Examine a candidate zone: compare zoneToTest to zoneRef
719 
720  // Get clearance used in zone to zone test. The policy used to
721  // obtain that value is now part of the zone object itself by way of
722  // ZONE_CONTAINER::GetClearance().
723  int zone2zoneClearance = zoneRef->GetClearance( zoneRef->GetLayer(), zoneToTest,
725 
726  // Keepout areas have no clearance, so set zone2zoneClearance to 1
727  // ( zone2zoneClearance = 0 can create problems in test functions)
728  if( zoneRef->GetIsKeepout() )
729  zone2zoneClearance = 1;
730 
731  // test for some corners of zoneRef inside zoneToTest
732  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
733  {
734  VECTOR2I currentVertex = *iterator;
735  wxPoint pt( currentVertex.x, currentVertex.y );
736 
737  if( smoothed_polys[ia2].Contains( currentVertex ) )
738  {
740  drcItem->SetItems( zoneRef, zoneToTest );
741 
742  MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
743  addMarkerToPcb( aCommit, marker );
744  }
745  }
746 
747  // test for some corners of zoneToTest inside zoneRef
748  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
749  {
750  VECTOR2I currentVertex = *iterator;
751  wxPoint pt( currentVertex.x, currentVertex.y );
752 
753  if( smoothed_polys[ia].Contains( currentVertex ) )
754  {
756  drcItem->SetItems( zoneToTest, zoneRef );
757 
758  MARKER_PCB* marker = new MARKER_PCB( drcItem, pt );
759  addMarkerToPcb( aCommit, marker );
760  }
761  }
762 
763  // Iterate through all the segments of refSmoothedPoly
764  std::map<wxPoint, int> conflictPoints;
765 
766  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
767  {
768  // Build ref segment
769  SEG refSegment = *refIt;
770 
771  // Iterate through all the segments in smoothed_polys[ia2]
772  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
773  {
774  // Build test segment
775  SEG testSegment = *testIt;
776  wxPoint pt;
777 
778  int ax1, ay1, ax2, ay2;
779  ax1 = refSegment.A.x;
780  ay1 = refSegment.A.y;
781  ax2 = refSegment.B.x;
782  ay2 = refSegment.B.y;
783 
784  int bx1, by1, bx2, by2;
785  bx1 = testSegment.A.x;
786  by1 = testSegment.A.y;
787  bx2 = testSegment.B.x;
788  by2 = testSegment.B.y;
789 
790  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
791  0,
792  ax1, ay1, ax2, ay2,
793  0,
794  zone2zoneClearance,
795  &pt.x, &pt.y );
796 
797  if( d < zone2zoneClearance )
798  {
799  if( conflictPoints.count( pt ) )
800  conflictPoints[ pt ] = std::min( conflictPoints[ pt ], d );
801  else
802  conflictPoints[ pt ] = d;
803  }
804  }
805  }
806 
807  for( const std::pair<const wxPoint, int>& conflict : conflictPoints )
808  {
809  int actual = conflict.second;
810  DRC_ITEM* drcItem;
811 
812  if( actual <= 0 )
813  {
815  }
816  else
817  {
818  drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
819 
820  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
822  MessageTextFromValue( userUnits(), zone2zoneClearance, true ),
823  MessageTextFromValue( userUnits(), conflict.second, true ) );
824 
825  drcItem->SetErrorMessage( m_msg );
826  }
827 
828  drcItem->SetItems( zoneRef, zoneToTest );
829 
830  MARKER_PCB* marker = new MARKER_PCB( drcItem, conflict.first );
831  addMarkerToPcb( aCommit, marker );
832  }
833  }
834  }
835 }
836 
837 
839 {
840  // Test copper items for clearance violations with vias, tracks and pads
841 
842  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
843  {
844  if( IsCopperLayer( brdItem->GetLayer() ) )
845  testCopperDrawItem( aCommit, brdItem );
846  }
847 
848  for( MODULE* module : m_pcb->Modules() )
849  {
850  TEXTE_MODULE& ref = module->Reference();
851  TEXTE_MODULE& val = module->Value();
852 
853  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
854  testCopperDrawItem( aCommit, &ref );
855 
856  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
857  testCopperDrawItem( aCommit, &val );
858 
859  if( module->IsNetTie() )
860  continue;
861 
862  for( BOARD_ITEM* item : module->GraphicalItems() )
863  {
864  if( IsCopperLayer( item->GetLayer() ) )
865  {
866  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
867  testCopperDrawItem( aCommit, item );
868  else if( item->Type() == PCB_MODULE_EDGE_T )
869  testCopperDrawItem( aCommit, item );
870  }
871  }
872  }
873 }
874 
875 
877 {
878  EDA_RECT bbox;
879  std::vector<SHAPE*> itemShapes;
880  DRAWSEGMENT* drawItem = dynamic_cast<DRAWSEGMENT*>( aItem );
881  EDA_TEXT* textItem = dynamic_cast<EDA_TEXT*>( aItem );
882 
883  if( drawItem )
884  {
885  bbox = drawItem->GetBoundingBox();
886  itemShapes = drawItem->MakeEffectiveShapes();
887  }
888  else if( textItem )
889  {
890  bbox = textItem->GetTextBox();
891 
892  int penWidth = textItem->GetEffectiveTextPenWidth();
893  std::vector<wxPoint> pts;
894  textItem->TransformTextShapeToSegmentList( pts );
895 
896  for( unsigned jj = 0; jj < pts.size(); jj += 2 )
897  itemShapes.push_back( new SHAPE_SEGMENT( pts[jj], pts[jj+1], penWidth ) );
898  }
899  else
900  {
901  wxFAIL_MSG( "unknown item type in testCopperDrawItem()" );
902  return;
903  }
904 
905  SHAPE_RECT bboxShape( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
906 
907  // Test tracks and vias
908  for( TRACK* track : m_pcb->Tracks() )
909  {
910  if( !track->IsOnLayer( aItem->GetLayer() ) )
911  continue;
912 
913  int minClearance = track->GetClearance( track->GetLayer(), aItem, &m_clearanceSource );
914  int actual = INT_MAX;
915  wxPoint pos;
916 
917  SHAPE_SEGMENT trackSeg( track->GetStart(), track->GetEnd(), track->GetWidth() );
918 
919  // Fast test to detect a track segment candidate inside the text bounding box
920  if( !bboxShape.Collide( &trackSeg, 0 ) )
921  continue;
922 
923  for( const SHAPE* shape : itemShapes )
924  {
925  int this_dist;
926 
927  if( shape->Collide( &trackSeg, minClearance, &this_dist ) )
928  {
929  if( this_dist < actual )
930  {
931  actual = this_dist;
932  pos = (wxPoint) shape->Centre();
933  }
934  }
935  }
936 
937  if( actual < INT_MAX )
938  {
940 
941  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
943  MessageTextFromValue( userUnits(), minClearance, true ),
944  MessageTextFromValue( userUnits(), std::max( 0, actual ), true ) );
945 
946  drcItem->SetErrorMessage( m_msg );
947  drcItem->SetItems( track, aItem );
948 
949  MARKER_PCB* marker = new MARKER_PCB( drcItem, pos );
950  addMarkerToPcb( aCommit, marker );
951  }
952  }
953 
954  // Test pads
955  for( D_PAD* pad : m_pcb->GetPads() )
956  {
957  if( !pad->IsOnLayer( aItem->GetLayer() ) )
958  continue;
959 
960  // Graphic items are allowed to act as net-ties within their own footprint
961  if( drawItem && pad->GetParent() == drawItem->GetParent() )
962  continue;
963 
964  int minClearance = pad->GetClearance( aItem->GetLayer(), aItem, &m_clearanceSource );
965  int actual = INT_MAX;
966 
967  // Fast test to detect a pad candidate inside the text bounding box
968  // Finer test (time consumming) is made only for pads near the text.
969  int bb_radius = pad->GetBoundingRadius() + minClearance;
970 
971  if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) )
972  continue;
973 
974  for( const SHAPE* bShape : itemShapes )
975  {
976  int this_dist;
977 
978  if( pad->GetEffectiveShape()->Collide( bShape, minClearance, &this_dist ) )
979  actual = std::min( actual, this_dist );
980  }
981 
982  if( actual < INT_MAX )
983  {
985 
986  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
988  MessageTextFromValue( userUnits(), minClearance, true ),
989  MessageTextFromValue( userUnits(), std::max( 0, actual ), true ) );
990 
991  drcItem->SetErrorMessage( m_msg );
992  drcItem->SetItems( pad, aItem );
993 
994  MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
995  addMarkerToPcb( aCommit, marker );
996  }
997  }
998 
999  for( SHAPE* shape : itemShapes )
1000  delete shape;
1001 }
1002 
1003 
1005 {
1007 
1009  m_board_outline_valid = false;
1010 
1011  if( m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1012  {
1013  m_board_outline_valid = true;
1014  }
1015  else
1016  {
1018 
1019  m_msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) );
1020 
1021  drcItem->SetErrorMessage( m_msg );
1022  drcItem->SetItems( m_pcb );
1023 
1024  MARKER_PCB* marker = new MARKER_PCB( drcItem, error_loc );
1025  addMarkerToPcb( aCommit, marker );
1026  }
1027 }
1028 
1029 
1031 {
1032  LSET disabledLayers = m_pcb->GetEnabledLayers().flip();
1033 
1034  // Perform the test only for copper layers
1035  disabledLayers &= LSET::AllCuMask();
1036 
1037  for( TRACK* track : m_pcb->Tracks() )
1038  {
1039  if( disabledLayers.test( track->GetLayer() ) )
1040  {
1042 
1043  m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ),
1044  track->GetLayerName() );
1045 
1046  drcItem->SetErrorMessage( m_msg );
1047  drcItem->SetItems( track );
1048 
1049  MARKER_PCB* marker = new MARKER_PCB( drcItem, track->GetPosition() );
1050  addMarkerToPcb( aCommit, marker );
1051  }
1052  }
1053 
1054  for( MODULE* module : m_pcb->Modules() )
1055  {
1057  [&]( BOARD_ITEM* child )
1058  {
1059  if( disabledLayers.test( child->GetLayer() ) )
1060  {
1062 
1063  m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ),
1064  child->GetLayerName() );
1065 
1066  drcItem->SetErrorMessage( m_msg );
1067  drcItem->SetItems( child );
1068 
1069  MARKER_PCB* marker = new MARKER_PCB( drcItem, child->GetPosition() );
1070  addMarkerToPcb( aCommit, marker );
1071  }
1072  } );
1073  }
1074 
1075  for( ZONE_CONTAINER* zone : m_pcb->Zones() )
1076  {
1077  if( disabledLayers.test( zone->GetLayer() ) )
1078  {
1080 
1081  m_msg.Printf( drcItem->GetErrorText() + _( "layer %s" ),
1082  zone->GetLayerName() );
1083 
1084  drcItem->SetErrorMessage( m_msg );
1085  drcItem->SetItems( zone );
1086 
1087  MARKER_PCB* marker = new MARKER_PCB( drcItem, zone->GetPosition() );
1088  addMarkerToPcb( aCommit, marker );
1089  }
1090  }
1091 }
1092 
1093 
1094 bool DRC::doPadToPadsDrc( BOARD_COMMIT& aCommit, D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd,
1095  int x_limit )
1096 {
1097  const static LSET all_cu = LSET::AllCuMask();
1098 
1099  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1100 
1101  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1102  {
1103  D_PAD* pad = *pad_list;
1104 
1105  if( pad == aRefPad )
1106  continue;
1107 
1108  // We can stop the test when pad->GetPosition().x > x_limit
1109  // because the list is sorted by X values
1110  if( pad->GetPosition().x > x_limit )
1111  break;
1112 
1113  // No problem if pads which are on copper layers are on different copper layers,
1114  // (pads can be only on a technical layer, to build complex pads)
1115  // but their hole (if any ) can create DRC error because they are on all
1116  // copper layers, so we test them
1117  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1118  ( pad->GetLayerSet() & all_cu ) != 0 &&
1119  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1120  {
1121  // if holes are in the same location and have the same size and shape,
1122  // this can be accepted
1123  if( pad->GetPosition() == aRefPad->GetPosition()
1124  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1125  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1126  {
1127  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1128  continue;
1129 
1130  // for oval holes: must also have the same orientation
1131  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1132  continue;
1133  }
1134 
1135  if( pad->GetDrillSize().x )
1136  {
1137  int minClearance = aRefPad->GetClearance( aRefPad->GetLayer(), nullptr,
1138  &m_clearanceSource );
1139  int actual;
1140 
1141  if( aRefPad->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
1142  {
1144 
1145  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
1147  MessageTextFromValue( userUnits(), minClearance, true ),
1148  MessageTextFromValue( userUnits(), actual, true ) );
1149 
1150  drcItem->SetErrorMessage( m_msg );
1151  drcItem->SetItems( pad, aRefPad );
1152 
1153  MARKER_PCB* marker = new MARKER_PCB( drcItem, pad->GetPosition() );
1154  addMarkerToPcb( aCommit, marker );
1155  return false;
1156  }
1157  }
1158 
1159  if( aRefPad->GetDrillSize().x )
1160  {
1161  int minClearance = pad->GetClearance( pad->GetLayer(), nullptr,
1162  &m_clearanceSource );
1163  int actual;
1164 
1165  if( pad->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
1166  {
1168 
1169  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
1171  MessageTextFromValue( userUnits(), minClearance, true ),
1172  MessageTextFromValue( userUnits(), actual, true ) );
1173 
1174  drcItem->SetErrorMessage( m_msg );
1175  drcItem->SetItems( aRefPad, pad );
1176 
1177  MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
1178  addMarkerToPcb( aCommit, marker );
1179  return false;
1180  }
1181  }
1182 
1183  continue;
1184  }
1185 
1186  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1187  // But no problem if pads have the same netcode (same net)
1188  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1189  continue;
1190 
1191  // If pads are equivalent (ie: from the same footprint with the same pad number)...
1192  if( pad->GetParent() == aRefPad->GetParent() && pad->PadNameEqual( aRefPad ) )
1193  {
1194  // ...and have nets, then they must be the same net
1195  if( pad->GetNetCode() && aRefPad->GetNetCode()
1196  && pad->GetNetCode() != aRefPad->GetNetCode() )
1197  {
1199 
1200  m_msg.Printf( drcItem->GetErrorText() + _( " (nets %s and %s)" ),
1201  pad->GetNetname(), aRefPad->GetNetname() );
1202 
1203  drcItem->SetErrorMessage( m_msg );
1204  drcItem->SetItems( pad, aRefPad );
1205 
1206  MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
1207  addMarkerToPcb( aCommit, marker );
1208  }
1209 
1210  continue;
1211  }
1212 
1213  // if either pad has no drill and is only on technical layers, not a clearance violation
1214  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1215  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1216  {
1217  continue;
1218  }
1219 
1220  for( PCB_LAYER_ID layer : aRefPad->GetLayerSet().Seq() )
1221  {
1222  int minClearance = aRefPad->GetClearance( layer, pad, &m_clearanceSource );
1223  int clearanceAllowed = minClearance - m_pcb->GetDesignSettings().GetDRCEpsilon();
1224  int actual;
1225 
1226  if( aRefPad->Collide( pad, clearanceAllowed, &actual ) )
1227  {
1229 
1230  m_msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
1232  MessageTextFromValue( userUnits(), minClearance, true ),
1233  MessageTextFromValue( userUnits(), actual, true ) );
1234 
1235  drcItem->SetErrorMessage( m_msg );
1236  drcItem->SetItems( aRefPad, pad );
1237 
1238  MARKER_PCB* marker = new MARKER_PCB( drcItem, aRefPad->GetPosition() );
1239  addMarkerToPcb( aCommit, marker );
1240  return false;
1241  }
1242  }
1243  }
1244 
1245  return true;
1246 }
1247 
1248 
1250 {
1251  Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
1252 }
1253 
1254 
1255 const int UI_EPSILON = Mils2iu( 5 );
1256 
1257 
1258 wxPoint DRC::GetLocation( TRACK* aTrack, ZONE_CONTAINER* aConflictZone )
1259 {
1260  SHAPE_POLY_SET* conflictOutline;
1261 
1262  PCB_LAYER_ID l = aTrack->GetLayer();
1263 
1264  if( aConflictZone->IsFilled() && aConflictZone->HasFilledPolysForLayer( l ) )
1265  conflictOutline = const_cast<SHAPE_POLY_SET*>( &aConflictZone->GetFilledPolysList( l ) );
1266  else
1267  conflictOutline = aConflictZone->Outline();
1268 
1269  wxPoint pt1 = aTrack->GetPosition();
1270  wxPoint pt2 = aTrack->GetEnd();
1271 
1272  // If the mid-point is in the zone, then that's a fine place for the marker
1273  if( conflictOutline->SquaredDistance( ( pt1 + pt2 ) / 2 ) == 0 )
1274  return ( pt1 + pt2 ) / 2;
1275 
1276  // Otherwise do a binary search for a "good enough" marker location
1277  else
1278  {
1279  while( GetLineLength( pt1, pt2 ) > UI_EPSILON )
1280  {
1281  if( conflictOutline->SquaredDistance( pt1 ) < conflictOutline->SquaredDistance( pt2 ) )
1282  pt2 = ( pt1 + pt2 ) / 2;
1283  else
1284  pt1 = ( pt1 + pt2 ) / 2;
1285  }
1286 
1287  // Once we're within UI_EPSILON pt1 and pt2 are "equivalent"
1288  return pt1;
1289  }
1290 }
1291 
1292 
1293 wxPoint DRC::GetLocation( TRACK* aTrack, const SEG& aConflictSeg )
1294 {
1295  wxPoint pt1 = aTrack->GetPosition();
1296  wxPoint pt2 = aTrack->GetEnd();
1297 
1298  // Do a binary search along the track for a "good enough" marker location
1299  while( GetLineLength( pt1, pt2 ) > UI_EPSILON )
1300  {
1301  if( aConflictSeg.SquaredDistance( pt1 ) < aConflictSeg.SquaredDistance( pt2 ) )
1302  pt2 = ( pt1 + pt2 ) / 2;
1303  else
1304  pt1 = ( pt1 + pt2 ) / 2;
1305  }
1306 
1307  // Once we're within UI_EPSILON pt1 and pt2 are "equivalent"
1308  return pt1;
1309 }
1310 
1311 
bool m_refillZones
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:62
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:712
std::vector< DRC_ITEM * > m_footprints
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
DIALOG_DRC * m_drcDialog
bool IsFilled() const
Definition: class_zone.h:190
bool Collide(const SHAPE_SEGMENT *aSeg, int aMinClearance, int *aActual=nullptr)
Definition: class_pad.cpp:900
TEXTE_MODULE & Reference()
Definition: class_module.h:485
void DestroyDRCDialog(int aReason)
Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.
int GetNetCode() const
Function GetNetCode.
RATSNEST_DRC_ITEMS_PROVIDER.
invalid board outline
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:206
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
void doTrackDrc(BOARD_COMMIT &aCommit, TRACK *aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterator aEndIt, bool aTestZones)
Test the current segment.
TEXTE_PCB class definition.
RC_ITEM * GetRCItem()
Function GetReporter returns the DRC_ITEM held within this MARKER so that its interface may be used.
Definition: marker_base.h:117
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
wxString m_msg
bool RunDRC(EDA_UNITS aUnits, BOARD &aBoard) override
Runs this provider against the given PCB with configured options (if any).
bool m_board_outline_valid
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
wxPoint GetPosition() const override
Definition: class_pad.h:165
int GetX() const
Definition: eda_rect.h:111
COMMIT & Add(EDA_ITEM *aItem)
Adds a new item to the model
Definition: commit.h:78
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Function GetEffectiveHoleShape Returns a list of SHAPE objects representing the pad's hole.
Definition: class_pad.cpp:239
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:800
Too small micro via drill.
items short two nets but are not a net tie
void setTransitions() override
Sets up handlers for various events.
void testTracks(BOARD_COMMIT &aCommit, wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
int m_largestClearance
void SetItems(EDA_ITEM *aItem, EDA_ITEM *bItem=nullptr, EDA_ITEM *cItem=nullptr, EDA_ITEM *dItem=nullptr)
Definition: rc_item.h:115
bool IsVisible() const
Definition: eda_text.h:186
PCB_DRAW_PANEL_GAL * GetCanvas() const override
Return a pointer to GAL-based canvas of given EDA draw frame.
void ResolveDRCExclusions()
Update markers to match recorded exclusions.
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:219
EDA_RECT GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:222
bool Ignore(int aDRCErrorCode)
returns true if the DRC error code's severity is SEVERITY_IGNORE
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:212
int GetWidth() const
Definition: eda_rect.h:119
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:282
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:140
void testCopperTextAndGraphics(BOARD_COMMIT &aCommit)
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:140
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:612
void testZones(BOARD_COMMIT &aCommit)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:553
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...
overlapping drilled holes break drill bits
EDA_UNITS userUnits() const
bool doPadToPadsDrc(BOARD_COMMIT &aCommit, D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Test the clearance between aRefPad and other pads.
ecoord SquaredDistance(const SEG &aSeg) const
Definition: seg.cpp:37
a copper item is too close to the board edge
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
SEG::ecoord SquaredDistance(VECTOR2I aPoint) const
Function SquaredDistance computes the minimum distance squared between aPoint and all the polygons in...
virtual wxPoint GetPosition() const
Definition: base_struct.h:337
DRAWINGS & GraphicalItems()
Definition: class_module.h:183
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:377
footprint has a courtyard but malformed (not convertible to a closed polygon with holes)
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
BOARD * m_pcb
bool RunDRC(EDA_UNITS aUnits, BOARD &aBoard) override
Runs this provider against the given PCB with configured options (if any).
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
const int UI_EPSILON
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:157
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:277
wxString m_clearanceSource
wxString GetErrorText() const
Definition: rc_item.h:165
BOARD * m_pcb
Too small via or pad drill.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:113
void testCopperDrawItem(BOARD_COMMIT &aCommit, BOARD_ITEM *aDrawing)
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...
bool IsNetTie() const
Definition: class_module.h:274
virtual int GetClearance(PCB_LAYER_ID aLayer, BOARD_ITEM *aItem=nullptr, wxString *aSource=nullptr) const
Function GetClearance returns the clearance in internal units.
PCB_EDIT_FRAME * m_editFrame
void Reset(RESET_REASON aReason) override
Function Reset() Brings the tool to a known, initial state.
PCB_LAYER_ID
A quick note on layer IDs:
bool m_testFootprints
bool m_doKeepoutTest
ZONE_FILLER_TOOL.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:934
LSET is a set of PCB_LAYER_IDs.
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:186
footprint courtyards overlap
#define NULL
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:29
MODULES & Modules()
Definition: class_board.h:266
PCB_EDIT_FRAME * m_editFrame
BOARD_DRC_ITEMS_PROVIDER is an implementation of the RC_ITEMS_PROVIDER interface which uses a BOARD i...
int lineNumber
at which line number, 1 based index.
Definition: ki_exception.h:125
copper area outlines intersect
SHAPE_POLY_SET.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:484
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, std::set< VECTOR2I > *aPreserveCorners) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly.
const wxPoint GetPosition() const
Definition: eda_rect.h:115
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
footprint has no courtyard defined
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:330
TOOL_EVENT.
Definition: tool_event.h:171
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:335
void Parse(std::vector< DRC_RULE * > &aRules, REPORTER *aReporter)
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:355
int GetErrorCode() const
Definition: rc_item.h:156
void SetFootprintsProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:229
void addMarkerToPcb(BOARD_COMMIT &aCommit, MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
track with at least one end not connected to anything
void TransformTextShapeToSegmentList(std::vector< wxPoint > &aCornerBuffer) const
Convert the text shape to a list of segment.
Definition: eda_text.cpp:583
friend class DIALOG_DRC
Design Rule Checker object that performs all the DRC tests.
static DRC_ITEM * Create(int aErrorCode)
Constructs a DRC_ITEM for the given error code.
std::vector< DRC_ITEM * > m_unconnected
SHAPE.
Definition: shape.h:74
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
items are unconnected
bool m_drcRun
copper area has a net but no pads in nets, which is suspicious
bool LoadRules()
Load the DRC rules.
const wxString & GetNetname() const
Function GetNetname.
via which isn't connected to anything
int GetHeight() const
Definition: eda_rect.h:120
bool Show(bool show) override
wxPoint GetPosition() const override
Definition: class_zone.cpp:206
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:712
Pad object description.
bool m_testTracksAgainstZones
bool m_footprintsTested
MODULE * GetParent() const
Definition: class_pad.h:111
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
bool m_board_outline_valid
Definition: seg.h:39
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aUseMils, EDA_DATA_TYPE aType)
Definition: base_units.cpp:124
void SetMarkersProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:213
void TestFootprints(NETLIST &aNetlist, BOARD *aBoard, std::vector< DRC_ITEM * > &aDRCList)
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
bool RunDRC(EDA_UNITS aUnits, BOARD &aBoard) override
Runs this provider against the given PCB with configured options (if any).
item on a disabled layer
SHAPE_POLY_SET m_board_outlines
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
ZONE_CONTAINERS & Zones()
Definition: class_board.h:280
int m_largestClearance
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
KIGFX::WS_PROXY_VIEW_ITEM * GetWorksheet() const
Class to handle a graphic segment.
#define ID_RULES_EDITOR
MODULE * module() const
#define _(s)
Definition: 3d_actions.cpp:33
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:325
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
const wxSize & GetDrillSize() const
Definition: class_pad.h:230
VECTOR2I A
Definition: seg.h:47
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
static TOOL_ACTION runDRC
Definition: pcb_actions.h:320
int GetY() const
Definition: eda_rect.h:112
RESET_REASON
Determines the reason of reset for a tool
Definition: tool_base.h:79
const wxPoint & GetEnd() const
Definition: class_track.h:115
int byteIndex
at which byte offset within the line, 1 based index
Definition: ki_exception.h:126
void testPadClearances(BOARD_COMMIT &aCommit)
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void Activate()
Function Activate() Runs the tool.
wxPoint GetPosition() const override
Definition: class_track.h:108
void testDisabledLayers(BOARD_COMMIT &aCommit)
void SetErrorMessage(const wxString &aMessage)
Definition: rc_item.h:113
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
bool IsDRCDialogShown()
Check to see if the DRC dialog is currently shown.
DIALOG_DRC * m_drcDialog
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:899
static REPORTER & GetInstance()
Definition: reporter.cpp:105
BOARD * GetBoard() const
static wxPoint GetLocation(TRACK *aTrack, ZONE_CONTAINER *aConflictZone)
Fetches a reasonable point for marking a violoation between two non-point objects.
EDGE_MODULE class definition.
void testUnconnected()
void RunTests(wxTextCtrl *aMessages=NULL)
Run all the tests specified with a previous call to SetSettings()
BOARD_ITEM_CONTAINER * GetParent() const
void testOutline(BOARD_COMMIT &aCommit)
Test that the board outline is contiguous and composed of valid elements.
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
DRAWINGS & Drawings()
Definition: class_board.h:275
std::vector< DRC_RULE * > m_DRCRules
void ShowBoardSetupDialog(const wxString &aInitialPage=wxEmptyString, const wxString &aErrorMsg=wxEmptyString, int aErrorCtrlId=-1, int aErrorLine=-1, int aErrorCol=-1)
Function ShowBoardSetupDialog.
VECTOR_DRC_ITEMS_PROVIDER is an implementation of the interface named DRC_ITEMS_PROVIDER which uses a...
void SetUnconnectedProvider(RC_ITEMS_PROVIDER *aProvider)
Definition: dialog_drc.cpp:221
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
bool HasFilledPolysForLayer(PCB_LAYER_ID aLayer) const
Definition: class_zone.h:602
TRACKS & Tracks()
Definition: class_board.h:257
bool m_doUnconnectedTest
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:218
std::vector< SHAPE * > MakeEffectiveShapes() const
Makes a set of SHAPE objects representing the DRAWSEGMENT.
bool RunDRC(EDA_UNITS aUnits, BOARD &aBoard) override
Runs this provider against the given PCB with configured options (if any).
std::vector< DRC_RULE * > m_rules
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
items are too close together
VECTOR2I B
Definition: seg.h:48