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