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