KiCad PCB EDA Suite
DRC Class Reference

Design Rule Checker object that performs all the DRC tests. More...

#include <drc.h>

Public Member Functions

 DRC (PCB_EDIT_FRAME *aPcbWindow)
 
 ~DRC ()
 
int DrcOnCreatingTrack (TRACK *aRefSeg, TRACK *aList)
 Function Drc tests the current segment and returns the result and displays the error in the status panel only if one exists. More...
 
int DrcOnCreatingZone (ZONE_CONTAINER *aArea, int aCornerIndex)
 Function Drc tests the outline segment starting at CornerIndex and returns the result and displays the error in the status panel only if one exists. More...
 
int TestZoneToZoneOutline (ZONE_CONTAINER *aZone, bool aCreateMarkers)
 Tests whether distance between zones complies with the DRC rules. More...
 
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 creates the MARKERS. More...
 
void DestroyDRCDialog (int aReason)
 Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence. More...
 
void SetSettings (bool aPad2PadTest, bool aUnconnectedTest, bool aZonesTest, bool aKeepoutTest, bool aRefillZones, bool aReportAllTrackErrors, const wxString &aReportName, bool aSaveReport)
 Save all the UI or test settings and may be called before running the tests. More...
 
void RunTests (wxTextCtrl *aMessages=NULL)
 Run all the tests specified with a previous call to SetSettings() More...
 
void ListUnconnectedPads ()
 Gather a list of all the unconnected pads and shows them in the dialog, and optionally prints a report of such. More...
 
MARKER_PCBGetCurrentMarker ()
 

Private Member Functions

void updatePointers ()
 Update needed pointers from the one pointer which is known not to change. More...
 
void addMarkerToPcb (MARKER_PCB *aMarker)
 Adds a DRC marker to the PCB through the COMMIT mechanism. More...
 
bool testNetClasses ()
 Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings. More...
 
void testTracks (wxWindow *aActiveWindow, bool aShowProgressBar)
 Perform the DRC on all tracks. More...
 
void testPad2Pad ()
 
void testDrilledHoles ()
 
void testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testCopperTextItem (BOARD_ITEM *aTextItem)
 
void testCopperDrawItem (DRAWSEGMENT *aDrawing)
 
void testCopperTextAndGraphics ()
 
void testDisabledLayers ()
 

Tests for items placed on disabled layers (causing false connections).

More...
 
void testOutline ()
 Test that the board outline is contiguous and composed of valid elements. More...
 
bool doNetClass (const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
 
bool doPadToPadsDrc (D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
 Test the clearance between aRefPad and other pads. More...
 
bool doTrackDrc (TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
 Test the current segment. More...
 
bool doTrackKeepoutDrc (TRACK *aRefSeg)
 Test the current segment or via. More...
 
bool doEdgeZoneDrc (ZONE_CONTAINER *aArea, int aCornerIndex)
 Test a segment in ZONE_CONTAINER * aArea: Test Edge inside other areas Test Edge too close other areas. More...
 
void doFootprintOverlappingDrc ()
 Test for footprint courtyard overlaps. More...
 
bool checkClearancePadToPad (D_PAD *aRefPad, D_PAD *aPad)
 
bool checkClearanceSegmToPad (const D_PAD *aPad, int aSegmentWidth, int aMinDist)
 Check the distance from a pad to segment. More...
 
bool checkLine (wxPoint aSegStart, wxPoint aSegEnd)
 Function checkLine (helper function used in drc calculations to see if one track is in contact with another track). More...
 

Static Private Member Functions

static bool checkMarginToCircle (wxPoint aCentre, int aRadius, int aLength)
 Check the distance from a point to a segment. More...
 

Private Attributes

bool m_doPad2PadTest
 
bool m_doUnconnectedTest
 
bool m_doZonesTest
 
bool m_doKeepoutTest
 
bool m_doCreateRptFile
 
bool m_refillZones
 
bool m_reportAllTrackErrors
 
wxString m_rptFilename
 
MARKER_PCBm_currentMarker
 
bool m_drcInLegacyRoutingMode
 in legacy canvas, when creating a track, the drc test must only display the error message, and do not create a DRC marker. More...
 
wxPoint m_padToTestPos
 
wxPoint m_segmEnd
 
double m_segmAngle
 
int m_segmLength
 
int m_xcliplo
 
int m_ycliplo
 
int m_xcliphi
 
int m_ycliphi
 
PCB_EDIT_FRAMEm_pcbEditorFrame
 The pcb frame editor which owns the board. More...
 
BOARDm_pcb
 
SHAPE_POLY_SET m_board_outlines
 The board outline including cutouts. More...
 
DIALOG_DRC_CONTROLm_drcDialog
 
DRC_MARKER_FACTORY m_markerFactory
 Class that generates markers. More...
 
DRC_LIST m_unconnected
 list of unconnected pads, as DRC_ITEMs More...
 

Friends

class DIALOG_DRC_CONTROL
 

Detailed Description

Design Rule Checker object that performs all the DRC tests.

The output of the checking goes to the BOARD file in the form of two MARKER lists. Those two lists are displayable in the drc dialog box. And they can optionally be sent to a text file on disk. This class is given access to the windows and the BOARD that it needs via its constructor or public access functions.

Definition at line 176 of file drc.h.

Constructor & Destructor Documentation

◆ DRC()

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 133 of file drc.cpp.

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 = true; // enable 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 }
bool m_refillZones
Definition: drc.h:188
bool m_doCreateRptFile
Definition: drc.h:187
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:229
int m_ycliplo
Definition: drc.h:222
int m_ycliphi
Definition: drc.h:224
int m_segmLength
Definition: drc.h:216
BOARD * m_pcb
Definition: drc.h:227
bool m_doKeepoutTest
Definition: drc.h:186
bool m_doZonesTest
Definition: drc.h:185
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:291
bool m_reportAllTrackErrors
Definition: drc.h:189
int m_xcliphi
Definition: drc.h:223
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
bool m_doPad2PadTest
Definition: drc.h:183
MARKER_PCB * m_currentMarker
Definition: drc.h:193
BOARD * GetBoard() const
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
void SetUnitsProvider(UNITS_PROVIDER aUnitsProvider)
Set the provider for the units (this will be called for each new marker constructed)
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201
int m_xcliplo
Definition: drc.h:221
bool m_doUnconnectedTest
Definition: drc.h:184
double m_segmAngle
Definition: drc.h:215

References PCB_BASE_FRAME::GetBoard(), EDA_DRAW_FRAME::GetUserUnits(), m_currentMarker, m_doCreateRptFile, m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_doZonesTest, m_drcDialog, m_drcInLegacyRoutingMode, m_markerFactory, m_pcb, m_pcbEditorFrame, m_refillZones, m_reportAllTrackErrors, m_segmAngle, m_segmLength, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, and DRC_MARKER_FACTORY::SetUnitsProvider().

◆ ~DRC()

DRC::~DRC ( )

Definition at line 165 of file drc.cpp.

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 }
size_t i
Definition: json11.cpp:597
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:232

References i, and m_unconnected.

Member Function Documentation

◆ addMarkerToPcb()

void DRC::addMarkerToPcb ( MARKER_PCB aMarker)
private

Adds a DRC marker to the PCB through the COMMIT mechanism.

Definition at line 102 of file drc.cpp.

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 }
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
MARKER_PCB * m_currentMarker
Definition: drc.h:193
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201

References COMMIT::Add(), m_currentMarker, m_drcInLegacyRoutingMode, m_pcbEditorFrame, BOARD_COMMIT::Push(), and EDA_DRAW_FRAME::SetMsgPanel().

Referenced by doFootprintOverlappingDrc(), doNetClass(), doTrackDrc(), testCopperDrawItem(), testCopperTextItem(), testDisabledLayers(), testDrilledHoles(), testKeepoutAreas(), testOutline(), testPad2Pad(), testTracks(), and testZones().

◆ checkClearancePadToPad()

bool DRC::checkClearancePadToPad ( D_PAD aRefPad,
D_PAD aPad 
)
private
Parameters
aRefPadThe reference pad to check
aPadAnother pad to check against
Returns
bool - true if clearance between aRefPad and aPad is >= dist_min, else false

Definition at line 866 of file drc_clearance_test_functions.cpp.

867 {
868  int dist;
869  double pad_angle;
870 
871  // Get the clearance between the 2 pads. this is the min distance between aRefPad and aPad
872  int dist_min = aRefPad->GetClearance( aPad );
873 
874  // relativePadPos is the aPad shape position relative to the aRefPad shape position
875  wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos();
876 
877  dist = KiROUND( EuclideanNorm( relativePadPos ) );
878 
879  // Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
880  int delta = dist - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius();
881 
882  if( delta >= dist_min )
883  return true;
884 
885  /* Here, pads are near and DRC depend on the pad shapes
886  * We must compare distance using a fine shape analysis
887  * Because a circle or oval shape is the easier shape to test, try to have
888  * aRefPad shape type = PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
889  * if aRefPad = TRAP. and aPad = RECT, also swap pads
890  * Swap aRefPad and aPad if needed
891  */
892  bool swap_pads;
893  swap_pads = false;
894 
895  // swap pads to make comparisons easier
896  // Note also a ROUNDRECT pad with a corner radius = r can be considered as
897  // a smaller RECT (size - 2*r) with a clearance increased by r
898  // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
899  if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
900  {
901  // pad ref shape is here oval, rect, roundrect, trapezoid or custom
902  switch( aPad->GetShape() )
903  {
904  case PAD_SHAPE_CIRCLE:
905  swap_pads = true;
906  break;
907 
908  case PAD_SHAPE_OVAL:
909  swap_pads = true;
910  break;
911 
912  case PAD_SHAPE_RECT:
913  case PAD_SHAPE_ROUNDRECT:
914  if( aRefPad->GetShape() != PAD_SHAPE_OVAL )
915  swap_pads = true;
916  break;
917 
918  case PAD_SHAPE_TRAPEZOID:
919  case PAD_SHAPE_CUSTOM:
920  break;
921  }
922  }
923 
924  if( swap_pads )
925  {
926  std::swap( aRefPad, aPad );
927  relativePadPos = -relativePadPos;
928  }
929 
930  // corners of aRefPad (used only for rect/roundrect/trap pad)
931  wxPoint polyref[4];
932  // corners of aRefPad (used only for custom pad)
933  SHAPE_POLY_SET polysetref;
934 
935  // corners of aPad (used only for rect/roundrect/trap pad)
936  wxPoint polycompare[4];
937  // corners of aPad (used only custom pad)
938  SHAPE_POLY_SET polysetcompare;
939 
940  /* Because pad exchange, aRefPad shape is PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL,
941  * if one of the 2 pads was a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
942  * Therefore, if aRefPad is a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID,
943  * aPad is also a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID
944  */
945  bool diag = true;
946 
947  switch( aRefPad->GetShape() )
948  {
949  case PAD_SHAPE_CIRCLE:
950 
951  /* One can use checkClearanceSegmToPad to test clearance
952  * aRefPad is like a track segment with a null length and a witdth = GetSize().x
953  */
954  m_segmLength = 0;
955  m_segmAngle = 0;
956 
957  m_segmEnd.x = m_segmEnd.y = 0;
958 
959  m_padToTestPos = relativePadPos;
960  diag = checkClearanceSegmToPad( aPad, aRefPad->GetSize().x, dist_min );
961  break;
962 
963  case PAD_SHAPE_TRAPEZOID:
964  case PAD_SHAPE_ROUNDRECT:
965  case PAD_SHAPE_RECT:
966  case PAD_SHAPE_CUSTOM:
967  // pad_angle = pad orient relative to the aRefPad orient
968  pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
969  NORMALIZE_ANGLE_POS( pad_angle );
970 
971  if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
972  {
973  int padRadius = aRefPad->GetRoundRectCornerRadius();
974  dist_min += padRadius;
975  GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ),
976  aRefPad->GetSize(), aRefPad->GetOrientation() );
977  }
978  else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM )
979  {
980  polysetref.Append( aRefPad->GetCustomShapeAsPolygon() );
981 
982  // The reference pad can be rotated. calculate the rotated
983  // coordiantes ( note, the ref pad position is the origin of
984  // coordinates for this drc test)
985  aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref,
986  wxPoint( 0, 0 ), aRefPad->GetOrientation() );
987  }
988  else
989  {
990  // BuildPadPolygon has meaning for rect a trapeziod shapes
991  // and returns the 4 corners
992  aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
993  }
994 
995  switch( aPad->GetShape() )
996  {
997  case PAD_SHAPE_ROUNDRECT:
998  case PAD_SHAPE_RECT:
999  case PAD_SHAPE_TRAPEZOID:
1000  case PAD_SHAPE_CUSTOM:
1001  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1002  {
1003  int padRadius = aPad->GetRoundRectCornerRadius();
1004  dist_min += padRadius;
1005  GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos,
1006  aPad->GetSize(), aPad->GetOrientation() );
1007  }
1008  else if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1009  {
1010  polysetcompare.Append( aPad->GetCustomShapeAsPolygon() );
1011 
1012  // The pad to compare can be rotated. calculate the rotated
1013  // coordinattes ( note, the pad to compare position
1014  // is the relativePadPos for this drc test
1015  aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare,
1016  relativePadPos, aPad->GetOrientation() );
1017  }
1018  else
1019  {
1020  aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() );
1021 
1022  // Move aPad shape to relativePadPos
1023  for( int ii = 0; ii < 4; ii++ )
1024  polycompare[ii] += relativePadPos;
1025  }
1026  // And now test polygons: We have 3 cases:
1027  // one poly is complex and the other is basic (has only 4 corners)
1028  // both polys are complex
1029  // both polys are basic (have only 4 corners) the most usual case
1030  if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0)
1031  {
1032  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
1033  // And now test polygons:
1034  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
1035  polycompare, 4, dist_min ) )
1036  diag = false;
1037  }
1038  else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount())
1039  {
1040  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
1041  // And now test polygons:
1042  if( !poly2polyDRC( (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(),
1043  polyref, 4, dist_min ) )
1044  diag = false;
1045  }
1046  else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() )
1047  {
1048  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
1049  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
1050 
1051  // And now test polygons:
1052  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
1053  (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), dist_min ) )
1054  diag = false;
1055  }
1056  else if( !poly2polyDRC( polyref, 4, polycompare, 4, dist_min ) )
1057  diag = false;
1058  break;
1059 
1060  default:
1061  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() );
1062  break;
1063  }
1064  break;
1065 
1066  case PAD_SHAPE_OVAL: /* an oval pad is like a track segment */
1067  {
1068  /* Create a track segment with same dimensions as the oval aRefPad
1069  * and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
1070  */
1071  int segm_width;
1072  m_segmAngle = aRefPad->GetOrientation(); // Segment orient.
1073 
1074  if( aRefPad->GetSize().y < aRefPad->GetSize().x ) // Build an horizontal equiv segment
1075  {
1076  segm_width = aRefPad->GetSize().y;
1077  m_segmLength = aRefPad->GetSize().x - aRefPad->GetSize().y;
1078  }
1079  else // Vertical oval: build an horizontal equiv segment and rotate 90.0 deg
1080  {
1081  segm_width = aRefPad->GetSize().x;
1082  m_segmLength = aRefPad->GetSize().y - aRefPad->GetSize().x;
1083  m_segmAngle += 900;
1084  }
1085 
1086  /* the start point must be 0,0 and currently relativePadPos
1087  * is relative the center of pad coordinate */
1088  wxPoint segstart;
1089  segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
1090 
1091  RotatePoint( &segstart, m_segmAngle ); // actual start point coordinate of the equivalent segment
1092  // Calculate segment end position relative to the segment origin
1093  m_segmEnd.x = -2 * segstart.x;
1094  m_segmEnd.y = -2 * segstart.y;
1095 
1096  // Recalculate the equivalent segment angle in 0,1 degrees
1097  // to prepare a call to checkClearanceSegmToPad()
1099 
1100  // move pad position relative to the segment origin
1101  m_padToTestPos = relativePadPos - segstart;
1102 
1103  // Use segment to pad check to test the second pad:
1104  diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
1105  break;
1106  }
1107 
1108  default:
1109  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unknown pad shape" ) );
1110  break;
1111  }
1112 
1113  return diag;
1114 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
int OutlineCount() const
Returns the number of outlines in the set
static const int dist[10][10]
Definition: ar_matrix.cpp:320
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
int m_segmLength
Definition: drc.h:216
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:241
int PointCount() const
Function PointCount()
wxPoint m_padToTestPos
Definition: drc.h:207
static const int delta[8][2]
Definition: solve.cpp:112
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:170
Class SHAPE_POLY_SET.
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:619
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Check the distance from a pad to segment.
wxPoint m_segmEnd
Definition: drc.h:208
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
wxPoint ShapePos() const
Definition: class_pad.cpp:550
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:341
bool poly2polyDRC(wxPoint *aTref, int aTrefCount, wxPoint *aTcompare, int aTcompareCount, int aDist)
DRC control: these functions make a DRC between pads, tracks and pads versus tracks.
void GetRoundRectCornerCenters(wxPoint aCenters[4], int aRadius, const wxPoint &aPosition, const wxSize &aSize, double aRotation)
Helper function GetRoundRectCornerCenters Has meaning only for rounded rect Returns the centers of th...
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:538
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
const wxSize & GetSize() const
Definition: class_pad.h:269
double m_segmAngle
Definition: drc.h:215
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)

References SHAPE_POLY_SET::Append(), ArcTangente(), D_PAD::BuildPadPolygon(), checkClearanceSegmToPad(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), D_PAD::CustomShapeAsPolygonToBoardPosition(), delta, dist, EuclideanNorm(), D_PAD::GetBoundingRadius(), D_PAD::GetClearance(), D_PAD::GetCustomShapeAsPolygon(), D_PAD::GetOrientation(), GetRoundRectCornerCenters(), D_PAD::GetRoundRectCornerRadius(), D_PAD::GetShape(), D_PAD::GetSize(), KiROUND(), m_padToTestPos, m_segmAngle, m_segmEnd, m_segmLength, NORMALIZE_ANGLE_POS(), SHAPE_POLY_SET::OutlineCount(), PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), poly2polyDRC(), RotatePoint(), and D_PAD::ShapePos().

Referenced by doPadToPadsDrc().

◆ checkClearanceSegmToPad()

bool DRC::checkClearanceSegmToPad ( const D_PAD aPad,
int  aSegmentWidth,
int  aMinDist 
)
private

Check the distance from a pad to segment.

This function uses several instance variable not passed in: m_segmLength = length of the segment being tested m_segmAngle = angle of the segment with the X axis; m_segmEnd = end coordinate of the segment m_padToTestPos = position of pad relative to the origin of segment

Parameters
aPadIs the pad involved in the check
aSegmentWidthwidth of the segment to test
aMinDistIs the minimum clearance needed
Returns
true distance >= dist_min, false if distance < dist_min

Definition at line 1122 of file drc_clearance_test_functions.cpp.

1123 {
1124  // Note:
1125  // we are using a horizontal segment for test, because we know here
1126  // only the length and orientation+ of the segment
1127  // Therefore the coordinates of the shape of pad to compare
1128  // must be calculated in a axis system rotated by m_segmAngle
1129  // and centered to the segment origin, before they can be tested
1130  // against the segment
1131  // We are using:
1132  // m_padToTestPos the position of the pad shape in this axis system
1133  // m_segmAngle the axis system rotation
1134 
1135  int segmHalfWidth = aSegmentWidth / 2;
1136  int distToLine = segmHalfWidth + aMinDist;
1137 
1138  wxSize padHalfsize; // half dimension of the pad
1139 
1140  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1141  {
1142  // For a custom pad, the pad size has no meaning, we only can
1143  // use the bounding radius
1144  padHalfsize.x = padHalfsize.y = aPad->GetBoundingRadius();
1145  }
1146  else
1147  {
1148  padHalfsize = aPad->GetSize() / 2;
1149  }
1150 
1151  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
1152  {
1153  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
1154  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
1155  }
1156 
1157  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1158  {
1159  /* Easy case: just test the distance between segment and pad centre
1160  * calculate pad coordinates in the X,Y axis with X axis = segment to test
1161  */
1163  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
1164  }
1165 
1166  /* calculate the bounding box of the pad, including the clearance and the segment width
1167  * if the line from 0 to m_segmEnd does not intersect this bounding box,
1168  * the clearance is always OK
1169  * But if intersect, a better analysis of the pad shape must be done.
1170  */
1171  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
1172  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
1173  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
1174  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
1175 
1176  wxPoint startPoint( 0, 0 );
1177  wxPoint endPoint = m_segmEnd;
1178 
1179  double orient = aPad->GetOrientation();
1180 
1181  RotatePoint( &startPoint, m_padToTestPos, -orient );
1182  RotatePoint( &endPoint, m_padToTestPos, -orient );
1183 
1184  if( checkLine( startPoint, endPoint ) )
1185  return true;
1186 
1187  /* segment intersects the bounding box. But there is not always a DRC error.
1188  * A fine analysis of the pad shape must be done.
1189  */
1190  switch( aPad->GetShape() )
1191  {
1192  case PAD_SHAPE_CIRCLE:
1193  // This case was already tested, so it cannot be found here.
1194  // it is here just to avoid compil warning, and to remember
1195  // it is already tested.
1196  return false;
1197 
1198  case PAD_SHAPE_OVAL:
1199  {
1200  /* an oval is a complex shape, but is a rectangle and 2 circles
1201  * these 3 basic shapes are more easy to test.
1202  *
1203  * In calculations we are using a vertical or horizontal oval shape
1204  * (i.e. a vertical or horizontal rounded segment)
1205  */
1206  wxPoint cstart = m_padToTestPos;
1207  wxPoint cend = m_padToTestPos; // center of each circle
1208  int delta = std::abs( padHalfsize.y - padHalfsize.x );
1209  int radius = std::min( padHalfsize.y, padHalfsize.x );
1210 
1211  if( padHalfsize.x > padHalfsize.y ) // horizontal equivalent segment
1212  {
1213  cstart.x -= delta;
1214  cend.x += delta;
1215  // Build the rectangular clearance area between the two circles
1216  // the rect starts at cstart.x and ends at cend.x and its height
1217  // is (radius + distToLine)*2
1218  m_xcliplo = cstart.x;
1219  m_ycliplo = cstart.y - radius - distToLine;
1220  m_xcliphi = cend.x;
1221  m_ycliphi = cend.y + radius + distToLine;
1222  }
1223  else // vertical equivalent segment
1224  {
1225  cstart.y -= delta;
1226  cend.y += delta;
1227  // Build the rectangular clearance area between the two circles
1228  // the rect starts at cstart.y and ends at cend.y and its width
1229  // is (radius + distToLine)*2
1230  m_xcliplo = cstart.x - distToLine - radius;
1231  m_ycliplo = cstart.y;
1232  m_xcliphi = cend.x + distToLine + radius;
1233  m_ycliphi = cend.y;
1234  }
1235 
1236  // Test the rectangular clearance area between the two circles (the rounded ends)
1237  // If the segment legth is zero, only check the endpoints, skip the rectangle
1238  if( m_segmLength && !checkLine( startPoint, endPoint ) )
1239  {
1240  return false;
1241  }
1242 
1243  // test the first end
1244  // Calculate the actual position of the circle, given the pad orientation:
1245  RotatePoint( &cstart, m_padToTestPos, orient );
1246 
1247  // Calculate the actual position of the circle in the new X,Y axis, relative
1248  // to the segment:
1249  RotatePoint( &cstart, m_segmAngle );
1250 
1251  if( !checkMarginToCircle( cstart, radius + distToLine, m_segmLength ) )
1252  {
1253  return false;
1254  }
1255 
1256  // test the second end
1257  RotatePoint( &cend, m_padToTestPos, orient );
1258  RotatePoint( &cend, m_segmAngle );
1259 
1260  if( !checkMarginToCircle( cend, radius + distToLine, m_segmLength ) )
1261  {
1262  return false;
1263  }
1264  }
1265  break;
1266 
1267  case PAD_SHAPE_ROUNDRECT:
1268  {
1269  // a round rect is a smaller rect, with a clearance augmented by the corners radius
1270  int r = aPad->GetRoundRectCornerRadius();
1271  padHalfsize.x -= r;
1272  padHalfsize.y -= r;
1273  distToLine += r;
1274  }
1275  // Fall through
1276  case PAD_SHAPE_RECT:
1277  // the area to test is a rounded rectangle.
1278  // this can be done by testing 2 rectangles and 4 circles (the corners)
1279 
1280  // Testing the first rectangle dimx + distToLine, dimy:
1281  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
1282  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
1283  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
1284  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
1285 
1286  if( !checkLine( startPoint, endPoint ) )
1287  return false;
1288 
1289  // Testing the second rectangle dimx , dimy + distToLine
1290  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
1291  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
1292  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
1293  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
1294 
1295  if( !checkLine( startPoint, endPoint ) )
1296  return false;
1297 
1298  // testing the 4 circles which are the clearance area of each corner:
1299 
1300  // testing the left top corner of the rectangle
1301  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1302  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1303  RotatePoint( &startPoint, m_padToTestPos, orient );
1304  RotatePoint( &startPoint, m_segmAngle );
1305 
1306  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1307  return false;
1308 
1309  // testing the right top corner of the rectangle
1310  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1311  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1312  RotatePoint( &startPoint, m_padToTestPos, orient );
1313  RotatePoint( &startPoint, m_segmAngle );
1314 
1315  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1316  return false;
1317 
1318  // testing the left bottom corner of the rectangle
1319  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1320  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1321  RotatePoint( &startPoint, m_padToTestPos, orient );
1322  RotatePoint( &startPoint, m_segmAngle );
1323 
1324  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1325  return false;
1326 
1327  // testing the right bottom corner of the rectangle
1328  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1329  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1330  RotatePoint( &startPoint, m_padToTestPos, orient );
1331  RotatePoint( &startPoint, m_segmAngle );
1332 
1333  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1334  return false;
1335 
1336  break;
1337 
1338  case PAD_SHAPE_TRAPEZOID:
1339  {
1340  wxPoint poly[4];
1341  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
1342 
1343  // Move shape to m_padToTestPos
1344  for( int ii = 0; ii < 4; ii++ )
1345  {
1346  poly[ii] += m_padToTestPos;
1347  RotatePoint( &poly[ii], m_segmAngle );
1348  }
1349 
1350  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ),
1351  wxPoint(m_segmLength,0), distToLine ) )
1352  return false;
1353  }
1354  break;
1355 
1356  case PAD_SHAPE_CUSTOM:
1357  {
1358  SHAPE_POLY_SET polyset;
1359  polyset.Append( aPad->GetCustomShapeAsPolygon() );
1360  // The pad can be rotated. calculate the coordinates
1361  // relatives to the segment being tested
1362  // Note, the pad position relative to the segment origin
1363  // is m_padToTestPos
1364  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1365  m_padToTestPos, orient );
1366 
1367  // Rotate all coordinates by m_segmAngle, because the segment orient
1368  // is m_segmAngle
1369  // we are using a horizontal segment for test, because we know here
1370  // only the lenght and orientation+ of the segment
1371  // therefore all coordinates of the pad to test must be rotated by
1372  // m_segmAngle (they are already relative to the segment origin)
1373  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1374  wxPoint( 0, 0 ), m_segmAngle );
1375 
1376  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1377 
1378  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1379  refpoly.PointCount(),
1380  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1381  distToLine ) )
1382  return false;
1383  }
1384  break;
1385  }
1386 
1387  return true;
1388 }
int m_ycliplo
Definition: drc.h:222
int m_ycliphi
Definition: drc.h:224
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc.h:216
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
int PointCount() const
Function PointCount()
wxPoint m_padToTestPos
Definition: drc.h:207
#define abs(a)
Definition: auxiliary.h:84
static const int delta[8][2]
Definition: solve.cpp:112
bool checkLine(wxPoint aSegStart, wxPoint aSegEnd)
Function checkLine (helper function used in drc calculations to see if one track is in contact with a...
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
Class SHAPE_POLY_SET.
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Check the distance from a point to a segment.
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:619
const wxSize & GetDelta() const
Definition: class_pad.h:272
int m_xcliphi
Definition: drc.h:223
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
wxPoint m_segmEnd
Definition: drc.h:208
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:341
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:538
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
const wxSize & GetSize() const
Definition: class_pad.h:269
int m_xcliplo
Definition: drc.h:221
double m_segmAngle
Definition: drc.h:215
#define min(a, b)
Definition: auxiliary.h:85
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)

References abs, SHAPE_POLY_SET::Append(), D_PAD::BuildPadPolygon(), checkLine(), checkMarginToCircle(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), D_PAD::CustomShapeAsPolygonToBoardPosition(), delta, D_PAD::GetBoundingRadius(), D_PAD::GetCustomShapeAsPolygon(), D_PAD::GetDelta(), D_PAD::GetOrientation(), D_PAD::GetRoundRectCornerRadius(), D_PAD::GetShape(), D_PAD::GetSize(), m_padToTestPos, m_segmAngle, m_segmEnd, m_segmLength, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, min, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), poly2segmentDRC(), and RotatePoint().

Referenced by checkClearancePadToPad(), and doTrackDrc().

◆ checkLine()

bool DRC::checkLine ( wxPoint  aSegStart,
wxPoint  aSegEnd 
)
private

Function checkLine (helper function used in drc calculations to see if one track is in contact with another track).

Helper function checkLine Test if a line intersects a bounding box (a rectangle) The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi return true if the line from aSegStart to aSegEnd is outside the bounding box.

Test if a line intersects a bounding box (a rectangle) The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi return true if the line from aSegStart to aSegEnd is outside the bounding box

Definition at line 1450 of file drc_clearance_test_functions.cpp.

1451 {
1452 #define WHEN_OUTSIDE return true
1453 #define WHEN_INSIDE
1454  int temp;
1455 
1456  if( aSegStart.x > aSegEnd.x )
1457  std::swap( aSegStart, aSegEnd );
1458 
1459  if( (aSegEnd.x <= m_xcliplo) || (aSegStart.x >= m_xcliphi) )
1460  {
1461  WHEN_OUTSIDE;
1462  }
1463 
1464  if( aSegStart.y < aSegEnd.y )
1465  {
1466  if( (aSegEnd.y <= m_ycliplo) || (aSegStart.y >= m_ycliphi) )
1467  {
1468  WHEN_OUTSIDE;
1469  }
1470 
1471  if( aSegStart.y < m_ycliplo )
1472  {
1473  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1474  (aSegEnd.y - aSegStart.y) );
1475 
1476  if( (aSegStart.x += temp) >= m_xcliphi )
1477  {
1478  WHEN_OUTSIDE;
1479  }
1480 
1481  aSegStart.y = m_ycliplo;
1482  WHEN_INSIDE;
1483  }
1484 
1485  if( aSegEnd.y > m_ycliphi )
1486  {
1487  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1488  (aSegEnd.y - aSegStart.y) );
1489 
1490  if( (aSegEnd.x -= temp) <= m_xcliplo )
1491  {
1492  WHEN_OUTSIDE;
1493  }
1494 
1495  aSegEnd.y = m_ycliphi;
1496  WHEN_INSIDE;
1497  }
1498 
1499  if( aSegStart.x < m_xcliplo )
1500  {
1501  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1502  (aSegEnd.x - aSegStart.x) );
1503  aSegStart.y += temp;
1504  aSegStart.x = m_xcliplo;
1505  WHEN_INSIDE;
1506  }
1507 
1508  if( aSegEnd.x > m_xcliphi )
1509  {
1510  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1511  (aSegEnd.x - aSegStart.x) );
1512  aSegEnd.y -= temp;
1513  aSegEnd.x = m_xcliphi;
1514  WHEN_INSIDE;
1515  }
1516  }
1517  else
1518  {
1519  if( (aSegStart.y <= m_ycliplo) || (aSegEnd.y >= m_ycliphi) )
1520  {
1521  WHEN_OUTSIDE;
1522  }
1523 
1524  if( aSegStart.y > m_ycliphi )
1525  {
1526  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1527  (aSegStart.y - aSegEnd.y) );
1528 
1529  if( (aSegStart.x += temp) >= m_xcliphi )
1530  {
1531  WHEN_OUTSIDE;
1532  }
1533 
1534  aSegStart.y = m_ycliphi;
1535  WHEN_INSIDE;
1536  }
1537 
1538  if( aSegEnd.y < m_ycliplo )
1539  {
1540  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1541  (aSegStart.y - aSegEnd.y) );
1542 
1543  if( (aSegEnd.x -= temp) <= m_xcliplo )
1544  {
1545  WHEN_OUTSIDE;
1546  }
1547 
1548  aSegEnd.y = m_ycliplo;
1549  WHEN_INSIDE;
1550  }
1551 
1552  if( aSegStart.x < m_xcliplo )
1553  {
1554  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1555  (aSegEnd.x - aSegStart.x) );
1556  aSegStart.y -= temp;
1557  aSegStart.x = m_xcliplo;
1558  WHEN_INSIDE;
1559  }
1560 
1561  if( aSegEnd.x > m_xcliphi )
1562  {
1563  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1564  (aSegEnd.x - aSegStart.x) );
1565  aSegEnd.y += temp;
1566  aSegEnd.x = m_xcliphi;
1567  WHEN_INSIDE;
1568  }
1569  }
1570 
1571  // Do not divide here to avoid rounding errors
1572  if( ( (aSegEnd.x + aSegStart.x) < m_xcliphi * 2 )
1573  && ( (aSegEnd.x + aSegStart.x) > m_xcliplo * 2) \
1574  && ( (aSegEnd.y + aSegStart.y) < m_ycliphi * 2 )
1575  && ( (aSegEnd.y + aSegStart.y) > m_ycliplo * 2 ) )
1576  {
1577  return false;
1578  }
1579  else
1580  {
1581  return true;
1582  }
1583 }
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
int m_ycliplo
Definition: drc.h:222
int m_ycliphi
Definition: drc.h:224
int m_xcliphi
Definition: drc.h:223
#define WHEN_INSIDE
int m_xcliplo
Definition: drc.h:221

References m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, USCALE(), WHEN_INSIDE, and WHEN_OUTSIDE.

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

◆ checkMarginToCircle()

bool DRC::checkMarginToCircle ( wxPoint  aCentre,
int  aRadius,
int  aLength 
)
staticprivate

Check the distance from a point to a segment.

Helper function checkMarginToCircle Check the distance between a circle (round pad, via or round end of track) and a segment.

The segment is expected starting at 0,0, and on the X axis (used to test DRC between a segment and a round pad, via or round end of a track

Parameters
aCentreThe coordinate of the circle's center
aRadiusA "keep out" radius centered over the circle
aLengthThe length of the segment (i.e. coordinate of end, because it is on the X axis)
Returns
bool - true if distance >= radius, else false when distance < aRadius

the segment is expected starting at 0,0, and on the X axis return true if distance >= aRadius

Definition at line 1397 of file drc_clearance_test_functions.cpp.

1398 {
1399  if( abs( aCentre.y ) >= aRadius ) // trivial case
1400  return true;
1401 
1402  // Here, distance between aCentre and X axis is < aRadius
1403  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1404  {
1405  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1406  return false; // aCentre is between the starting point and the ending point of the segm
1407 
1408  if( aCentre.x > aLength ) // aCentre is after the ending point
1409  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1410 
1411  if( EuclideanNorm( aCentre ) < aRadius )
1412  // distance between aCentre and the starting point or the ending point is < aRadius
1413  return false;
1414  }
1415 
1416  return true;
1417 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
#define abs(a)
Definition: auxiliary.h:84

References abs, and EuclideanNorm().

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

◆ DestroyDRCDialog()

void DRC::DestroyDRCDialog ( int  aReason)

Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.

Parameters
aReasonIndication of which button was clicked to cause the destruction. if aReason == wxID_OK, design parameters values which can be entered from the dialog will bbe saved in design parameters list

Definition at line 121 of file drc.cpp.

122 {
123  if( m_drcDialog )
124  {
126 
127  m_drcDialog->Destroy();
128  m_drcDialog = NULL;
129  }
130 }
bool m_doCreateRptFile
Definition: drc.h:187
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:229
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:184
wxString m_rptFilename
Definition: drc.h:191

References DIALOG_DRC_CONTROL::GetRptSettings(), m_doCreateRptFile, m_drcDialog, and m_rptFilename.

Referenced by DIALOG_DRC_CONTROL::OnActivateDlg(), DIALOG_DRC_CONTROL::OnCancelClick(), and DIALOG_PLOT::onRunDRC().

◆ doEdgeZoneDrc()

bool DRC::doEdgeZoneDrc ( ZONE_CONTAINER aArea,
int  aCornerIndex 
)
private

Test a segment in ZONE_CONTAINER * aArea: Test Edge inside other areas Test Edge too close other areas.

Parameters
aAreaThe current area.
aCornerIndexThe first corner of the segment to test.
Returns
bool - false if DRC error or true if OK

Definition at line 768 of file drc_clearance_test_functions.cpp.

769 {
770  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
771  return true;
772  // Get polygon, contour and vertex index.
774 
775  // If the vertex does not exist, there is no conflict
776  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
777  return true;
778 
779  // Retrieve the selected contour
780  SHAPE_LINE_CHAIN contour;
781  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
782 
783  // Retrieve the segment that starts at aCornerIndex-th corner.
784  SEG selectedSegment = contour.Segment( index.m_vertex );
785 
786  VECTOR2I start = selectedSegment.A;
787  VECTOR2I end = selectedSegment.B;
788 
789  // iterate through all areas
790  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
791  {
792  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
793  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
794  aArea->GetZoneClearance() );
795 
796  // test for same layer
797  if( area_to_test->GetLayer() != aArea->GetLayer() )
798  continue;
799 
800  // Test for same net
801  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
802  continue;
803 
804  // test for same priority
805  if( area_to_test->GetPriority() != aArea->GetPriority() )
806  continue;
807 
808  // test for same type
809  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
810  continue;
811 
812  // For keepout, there is no clearance, so use a minimal value for it
813  // use 1, not 0 as value to avoid some issues in tests
814  if( area_to_test->GetIsKeepout() )
815  zone_clearance = 1;
816 
817  // test for ending line inside area_to_test
818  if( area_to_test->Outline()->Contains( end ) )
819  {
820  wxPoint pos( end.x, end.y );
822  m_markerFactory.NewMarker( pos, aArea, area_to_test, DRCE_ZONES_INTERSECT );
823  return false;
824  }
825 
826  // now test spacing between areas
827  int ax1 = start.x;
828  int ay1 = start.y;
829  int ax2 = end.x;
830  int ay2 = end.y;
831 
832  // Iterate through all edges in the polygon.
834  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
835  {
836  SEG segment = *iterator;
837 
838  int bx1 = segment.A.x;
839  int by1 = segment.A.y;
840  int bx2 = segment.B.x;
841  int by2 = segment.B.y;
842 
843  int x, y; // variables containing the intersecting point coordinates
844  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
845  0,
846  ax1, ay1, ax2, ay2,
847  0,
848  zone_clearance,
849  &x, &y );
850 
851  if( d < zone_clearance )
852  {
853  // COPPERAREA_COPPERAREA error : edge intersect or too close
855  wxPoint( x, y ), aArea, area_to_test, DRCE_ZONES_TOO_CLOSE );
856  return false;
857  }
858 
859  }
860  }
861 
862  return true;
863 }
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, bool aIgnoreHoles=false) const
Returns true if a given subpolygon contains the point aP.
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
int GetNetCode() const
Function GetNetCode.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:234
Struct VERTEX_INDEX.
Class SEGMENT_ITERATOR_TEMPLATE.
#define DRCE_ZONES_INTERSECT
copper area outlines intersect
Definition: drc.h:69
BOARD * m_pcb
Definition: drc.h:227
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
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 GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Function GetRelativeIndices.
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:621
MARKER_PCB * m_currentMarker
Definition: drc.h:193
Definition: seg.h:36
SEG Segment(int aIndex)
Function Segment()
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:97
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:44
#define DRCE_ZONES_TOO_CLOSE
copper area outlines are too close
Definition: drc.h:70
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
int GetZoneClearance() const
Definition: class_zone.h:188
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
VECTOR2I B
Definition: seg.h:45

References SEG::A, SEG::B, SHAPE_POLY_SET::Contains(), DRCE_ZONES_INTERSECT, DRCE_ZONES_TOO_CLOSE, BOARD::GetArea(), BOARD::GetAreaCount(), GetClearanceBetweenSegments(), ZONE_CONTAINER::GetIsKeepout(), ZONE_CONTAINER::GetLayer(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPriority(), SHAPE_POLY_SET::GetRelativeIndices(), ZONE_CONTAINER::GetZoneClearance(), ZONE_CONTAINER::IsOnCopperLayer(), SHAPE_POLY_SET::IterateSegmentsWithHoles(), SHAPE_POLY_SET::VERTEX_INDEX::m_contour, m_currentMarker, m_markerFactory, m_pcb, SHAPE_POLY_SET::VERTEX_INDEX::m_polygon, SHAPE_POLY_SET::VERTEX_INDEX::m_vertex, max, DRC_MARKER_FACTORY::NewMarker(), ZONE_CONTAINER::Outline(), SHAPE_POLY_SET::Polygon(), SHAPE_LINE_CHAIN::Segment(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DrcOnCreatingZone().

◆ doFootprintOverlappingDrc()

void DRC::doFootprintOverlappingDrc ( )
private

Test for footprint courtyard overlaps.

Definition at line 1441 of file drc.cpp.

1442 {
1443  DRC_COURTYARD_OVERLAP drc_overlap(
1444  m_markerFactory, [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1445 
1446  drc_overlap.RunDRC( *m_pcb );
1447 }
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
bool RunDRC(BOARD &aBoard) const override
Runs this provider against the given PCB with configured options (if any).
A class that provides the courtyard-based DRC checks.
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230

References addMarkerToPcb(), m_markerFactory, m_pcb, and DRC_COURTYARD_OVERLAP::RunDRC().

Referenced by RunTests().

◆ doNetClass()

bool DRC::doNetClass ( const std::shared_ptr< NETCLASS > &  aNetClass,
wxString &  msg 
)
private

Definition at line 577 of file drc.cpp.

578 {
579  bool ret = true;
580 
582 
583 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
584 
585 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
586  if( nc->GetClearance() < g.m_MinClearance )
587  {
588  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
589  GetChars( nc->GetName() ),
590  FmtVal( nc->GetClearance() ),
591  FmtVal( g.m_TrackClearance )
592  );
593 
595  m_currentMarker = nullptr;
596  ret = false;
597  }
598 #endif
599 
600  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
601  {
602  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
603  GetChars( nc->GetName() ),
604  FmtVal( nc->GetTrackWidth() ),
606  );
607 
609  ret = false;
610  }
611 
612  if( nc->GetViaDiameter() < g.m_ViasMinSize )
613  {
614  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
615  GetChars( nc->GetName() ),
616  FmtVal( nc->GetViaDiameter() ),
617  FmtVal( g.m_ViasMinSize )
618  );
619 
621  ret = false;
622  }
623 
624  if( nc->GetViaDrill() < g.m_ViasMinDrill )
625  {
626  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
627  GetChars( nc->GetName() ),
628  FmtVal( nc->GetViaDrill() ),
630  );
631 
633  ret = false;
634  }
635 
636  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
637  {
638  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
639  GetChars( nc->GetName() ),
640  FmtVal( nc->GetuViaDiameter() ),
641  FmtVal( g.m_MicroViasMinSize ) );
642 
644  ret = false;
645  }
646 
647  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
648  {
649  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
650  GetChars( nc->GetName() ),
651  FmtVal( nc->GetuViaDrill() ),
653 
655  ret = false;
656  }
657 
658  return ret;
659 }
#define DRCE_NETCLASS_TRACKWIDTH
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc.h:79
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:80
BOARD * m_pcb
Definition: drc.h:227
#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
int m_TrackMinWidth
track min value for width ((min copper size value
int m_ViasMinSize
vias (not micro vias) min diameter
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
int m_ViasMinDrill
vias (not micro vias) min drill diameter
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:82
int m_MicroViasMinSize
micro vias (not vias) min diameter
#define FmtVal(x)
MARKER_PCB * m_currentMarker
Definition: drc.h:193
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
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
#define DRCE_NETCLASS_uVIASIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc.h:83
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.

References addMarkerToPcb(), DRCE_NETCLASS_CLEARANCE, DRCE_NETCLASS_TRACKWIDTH, DRCE_NETCLASS_uVIADRILLSIZE, DRCE_NETCLASS_uVIASIZE, DRCE_NETCLASS_VIADRILLSIZE, DRCE_NETCLASS_VIASIZE, FmtVal, GetChars(), BOARD::GetDesignSettings(), m_currentMarker, m_markerFactory, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, m_pcb, BOARD_DESIGN_SETTINGS::m_TrackMinWidth, BOARD_DESIGN_SETTINGS::m_ViasMinDrill, BOARD_DESIGN_SETTINGS::m_ViasMinSize, and DRC_MARKER_FACTORY::NewMarker().

Referenced by testNetClasses().

◆ doPadToPadsDrc()

bool DRC::doPadToPadsDrc ( D_PAD aRefPad,
D_PAD **  aStart,
D_PAD **  aEnd,
int  x_limit 
)
private

Test the clearance between aRefPad and other pads.

The pad list must be sorted by x coordinate.

Parameters
aRefPadis the pad to test
aStartis the first pad of the list to test against aRefPad
aEndis the end of the list and is not included
x_limitis used to stop the test (i.e. when the current pad pos X in list exceeds this limit, because the list is sorted by X coordinate)

Definition at line 1309 of file drc.cpp.

1310 {
1311  const static LSET all_cu = LSET::AllCuMask();
1312 
1313  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1314 
1315  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1316  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1317  * Therefore, this dummy pad is a circle or an oval.
1318  * A pad must have a parent because some functions expect a non null parent
1319  * to find the parent board, and some other data
1320  */
1321  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1322  D_PAD dummypad( &dummymodule );
1323 
1324  // Ensure the hole is on all copper layers
1325  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1326 
1327  // Use the minimal local clearance value for the dummy pad.
1328  // The clearance of the active pad will be used as minimum distance to a hole
1329  // (a value = 0 means use netclass value)
1330  dummypad.SetLocalClearance( 1 );
1331 
1332  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1333  {
1334  D_PAD* pad = *pad_list;
1335 
1336  if( pad == aRefPad )
1337  continue;
1338 
1339  // We can stop the test when pad->GetPosition().x > x_limit
1340  // because the list is sorted by X values
1341  if( pad->GetPosition().x > x_limit )
1342  break;
1343 
1344  // No problem if pads which are on copper layers are on different copper layers,
1345  // (pads can be only on a technical layer, to build complex pads)
1346  // but their hole (if any ) can create DRC error because they are on all
1347  // copper layers, so we test them
1348  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1349  ( pad->GetLayerSet() & all_cu ) != 0 &&
1350  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1351  {
1352  // if holes are in the same location and have the same size and shape,
1353  // this can be accepted
1354  if( pad->GetPosition() == aRefPad->GetPosition()
1355  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1356  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1357  {
1358  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1359  continue;
1360 
1361  // for oval holes: must also have the same orientation
1362  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1363  continue;
1364  }
1365 
1366  /* Here, we must test clearance between holes and pads
1367  * dummy pad size and shape is adjusted to pad drill size and shape
1368  */
1369  if( pad->GetDrillSize().x )
1370  {
1371  // pad under testing has a hole, test this hole against pad reference
1372  dummypad.SetPosition( pad->GetPosition() );
1373  dummypad.SetSize( pad->GetDrillSize() );
1374  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1376  dummypad.SetOrientation( pad->GetOrientation() );
1377 
1378  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1379  {
1380  // here we have a drc error on pad!
1382  return false;
1383  }
1384  }
1385 
1386  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1387  {
1388  dummypad.SetPosition( aRefPad->GetPosition() );
1389  dummypad.SetSize( aRefPad->GetDrillSize() );
1390  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1392  dummypad.SetOrientation( aRefPad->GetOrientation() );
1393 
1394  if( !checkClearancePadToPad( pad, &dummypad ) )
1395  {
1396  // here we have a drc error on aRefPad!
1398  return false;
1399  }
1400  }
1401 
1402  continue;
1403  }
1404 
1405  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1406  // But no problem if pads have the same netcode (same net)
1407  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1408  continue;
1409 
1410  // if pads are from the same footprint
1411  if( pad->GetParent() == aRefPad->GetParent() )
1412  {
1413  // and have the same pad number ( equivalent pads )
1414 
1415  // one can argue that this 2nd test is not necessary, that any
1416  // two pads from a single module are acceptable. This 2nd test
1417  // should eventually be a configuration option.
1418  if( pad->PadNameEqual( aRefPad ) )
1419  continue;
1420  }
1421 
1422  // if either pad has no drill and is only on technical layers, not a clearance violation
1423  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1424  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1425  {
1426  continue;
1427  }
1428 
1429  if( !checkClearancePadToPad( aRefPad, pad ) )
1430  {
1431  // here we have a drc error!
1433  return false;
1434  }
1435  }
1436 
1437  return true;
1438 }
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
int GetNetCode() const
Function GetNetCode.
#define DRCE_PAD_NEAR_PAD1
pad too close to pad
Definition: drc.h:66
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc.h:72
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:207
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
BOARD * m_pcb
Definition: drc.h:227
Class LSET is a set of PCB_LAYER_IDs.
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
MODULE * GetParent() const
Definition: class_pad.h:162
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:193
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
const wxPoint GetPosition() const override
Definition: class_pad.h:220
void SetPosition(const wxPoint &aPos) override

References LSET::AllCuMask(), checkClearancePadToPad(), DRCE_HOLE_NEAR_PAD, DRCE_PAD_NEAR_PAD1, D_PAD::GetDrillShape(), D_PAD::GetDrillSize(), D_PAD::GetLayerSet(), BOARD_CONNECTED_ITEM::GetNetCode(), D_PAD::GetOrientation(), D_PAD::GetParent(), D_PAD::GetPosition(), m_currentMarker, m_markerFactory, m_pcb, DRC_MARKER_FACTORY::NewMarker(), PAD_DRILL_SHAPE_CIRCLE, PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, D_PAD::PadNameEqual(), D_PAD::SetLayerSet(), D_PAD::SetLocalClearance(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), and D_PAD::SetSize().

Referenced by testPad2Pad().

◆ doTrackDrc()

bool DRC::doTrackDrc ( TRACK aRefSeg,
TRACK aStart,
bool  doPads = true 
)
private

Test the current segment.

Parameters
aRefSegThe segment to test
aStartthe first item of track list to test against (usually BOARD::m_Track)
doPadstrue if should do pads test
Returns
bool - true if no problems, else false and m_currentMarker is filled in with the problem information.

Definition at line 138 of file drc_clearance_test_functions.cpp.

139 {
140  TRACK* track;
141  wxPoint delta; // length on X and Y axis of segments
142  LSET layerMask;
143  int net_code_ref;
144  wxPoint shape_pos;
145 
146  std::vector<MARKER_PCB*> markers;
147 
148  auto commitMarkers = [&]()
149  {
150  // In legacy routing mode, do not add markers to the board.
151  // only shows the drc error message
153  {
154  while( markers.size() > 0 )
155  {
156  m_pcbEditorFrame->SetMsgPanel( markers.back() );
157  delete markers.back();
158  markers.pop_back();
159  }
160  }
161  else
162  {
163  BOARD_COMMIT commit( m_pcbEditorFrame );
164 
165  for( auto marker : markers )
166  commit.Add( marker );
167 
168  commit.Push( wxEmptyString, false, false );
169  }
170  };
171 
172  // Returns false if we should return false from call site, or true to continue
173  auto handleNewMarker = [&]() -> bool
174  {
176  {
177  if( markers.size() > 0 )
178  commitMarkers();
179 
180  return false;
181  }
182  else
183  return true;
184  };
185 
186  NETCLASSPTR netclass = aRefSeg->GetNetClass();
188 
189  /* In order to make some calculations more easier or faster,
190  * pads and tracks coordinates will be made relative to the reference segment origin
191  */
192  wxPoint origin = aRefSeg->GetStart(); // origin will be the origin of other coordinates
193 
194  m_segmEnd = delta = aRefSeg->GetEnd() - origin;
195  m_segmAngle = 0;
196 
197  layerMask = aRefSeg->GetLayerSet();
198  net_code_ref = aRefSeg->GetNetCode();
199 
200  /******************************************/
201  /* Phase 0 : via DRC tests : */
202  /******************************************/
203 
204  if( aRefSeg->Type() == PCB_VIA_T )
205  {
206  VIA *refvia = static_cast<VIA*>( aRefSeg );
207  wxPoint refviaPos = refvia->GetPosition();
208 
209  // test if the via size is smaller than minimum
210  if( refvia->GetViaType() == VIA_MICROVIA )
211  {
212  if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
213  {
214  markers.push_back(
215  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA ) );
216 
217  if( !handleNewMarker() )
218  return false;
219  }
220 
221  if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
222  {
223  markers.push_back( m_markerFactory.NewMarker(
224  refviaPos, refvia, DRCE_TOO_SMALL_MICROVIA_DRILL ) );
225 
226  if( !handleNewMarker() )
227  return false;
228  }
229  }
230  else
231  {
232  if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
233  {
234  markers.push_back(
235  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA ) );
236 
237  if( !handleNewMarker() )
238  return false;
239  }
240 
241  if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
242  {
243  markers.push_back(
244  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_TOO_SMALL_VIA_DRILL ) );
245 
246  if( !handleNewMarker() )
247  return false;
248  }
249  }
250 
251  // test if via's hole is bigger than its diameter
252  // This test is necessary since the via hole size and width can be modified
253  // and a default via hole can be bigger than some vias sizes
254  if( refvia->GetDrillValue() > refvia->GetWidth() )
255  {
256  markers.push_back(
257  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_VIA_HOLE_BIGGER ) );
258 
259  if( !handleNewMarker() )
260  return false;
261  }
262 
263  // test if the type of via is allowed due to design rules
264  if( refvia->GetViaType() == VIA_MICROVIA && !dsnSettings.m_MicroViasAllowed )
265  {
266  markers.push_back(
267  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_MICRO_VIA_NOT_ALLOWED ) );
268  if( !handleNewMarker() )
269  return false;
270  }
271 
272  // test if the type of via is allowed due to design rules
273  if( refvia->GetViaType() == VIA_BLIND_BURIED && !dsnSettings.m_BlindBuriedViaAllowed )
274  {
275  markers.push_back(
276  m_markerFactory.NewMarker( refviaPos, refvia, DRCE_BURIED_VIA_NOT_ALLOWED ) );
277 
278  if( !handleNewMarker() )
279  return false;
280  }
281 
282  // For microvias: test if they are blind vias and only between 2 layers
283  // because they are used for very small drill size and are drill by laser
284  // and **only one layer** can be drilled
285  if( refvia->GetViaType() == VIA_MICROVIA )
286  {
287  PCB_LAYER_ID layer1, layer2;
288  bool err = true;
289 
290  refvia->LayerPair( &layer1, &layer2 );
291 
292  if( layer1 > layer2 )
293  std::swap( layer1, layer2 );
294 
295  if( layer2 == B_Cu && layer1 == dsnSettings.GetCopperLayerCount() - 2 )
296  err = false;
297  else if( layer1 == F_Cu && layer2 == In1_Cu )
298  err = false;
299 
300  if( err )
301  {
302  markers.push_back( m_markerFactory.NewMarker(
303  refviaPos, refvia, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR ) );
304 
305  if( !handleNewMarker() )
306  return false;
307  }
308  }
309 
310  }
311  else // This is a track segment
312  {
313  if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth )
314  {
315  wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
316 
317  markers.push_back( m_markerFactory.NewMarker(
318  refsegMiddle, aRefSeg, DRCE_TOO_SMALL_TRACK_WIDTH ) );
319 
320  if( !handleNewMarker() )
321  return false;
322  }
323  }
324 
325  // for a non horizontal or vertical segment Compute the segment angle
326  // in tenths of degrees and its length
327  if( delta.x || delta.y )
328  {
329  // Compute the segment angle in 0,1 degrees
331 
332  // Compute the segment length: we build an equivalent rotated segment,
333  // this segment is horizontal, therefore dx = length
334  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
335  }
336 
337  m_segmLength = delta.x;
338 
339  /******************************************/
340  /* Phase 1 : test DRC track to pads : */
341  /******************************************/
342 
343  /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
344  * but having a hole
345  * This dummy pad has the size and shape of the hole
346  * to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
347  * Therefore, this dummy pad is a circle or an oval.
348  * A pad must have a parent because some functions expect a non null parent
349  * to find the parent board, and some other data
350  */
351  MODULE dummymodule( m_pcb ); // Creates a dummy parent
352  D_PAD dummypad( &dummymodule );
353 
354  dummypad.SetLayerSet( LSET::AllCuMask() ); // Ensure the hole is on all layers
355 
356  // Compute the min distance to pads
357  if( testPads )
358  {
359  unsigned pad_count = m_pcb->GetPadCount();
360 
361  auto pads = m_pcb->GetPads();
362 
363  for( unsigned ii = 0; ii < pad_count; ++ii )
364  {
365  D_PAD* pad = pads[ii];
366  SEG padSeg( pad->GetPosition(), pad->GetPosition() );
367 
368 
369  /* No problem if pads are on another layer,
370  * But if a drill hole exists (a pad on a single layer can have a hole!)
371  * we must test the hole
372  */
373  if( !( pad->GetLayerSet() & layerMask ).any() )
374  {
375  /* We must test the pad hole. In order to use the function
376  * checkClearanceSegmToPad(),a pseudo pad is used, with a shape and a
377  * size like the hole
378  */
379  if( pad->GetDrillSize().x == 0 )
380  continue;
381 
382  dummypad.SetSize( pad->GetDrillSize() );
383  dummypad.SetPosition( pad->GetPosition() );
384  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
386  dummypad.SetOrientation( pad->GetOrientation() );
387 
388  m_padToTestPos = dummypad.GetPosition() - origin;
389 
390  if( !checkClearanceSegmToPad( &dummypad, aRefSeg->GetWidth(),
391  netclass->GetClearance() ) )
392  {
393  markers.push_back( m_markerFactory.NewMarker(
394  aRefSeg, pad, padSeg, DRCE_TRACK_NEAR_THROUGH_HOLE ) );
395 
396  if( !handleNewMarker() )
397  return false;
398  }
399 
400  continue;
401  }
402 
403  // The pad must be in a net (i.e pt_pad->GetNet() != 0 )
404  // but no problem if the pad netcode is the current netcode (same net)
405  if( pad->GetNetCode() // the pad must be connected
406  && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok
407  continue;
408 
409  // DRC for the pad
410  shape_pos = pad->ShapePos();
411  m_padToTestPos = shape_pos - origin;
412 
413  if( !checkClearanceSegmToPad( pad, aRefSeg->GetWidth(), aRefSeg->GetClearance( pad ) ) )
414  {
415  markers.push_back(
416  m_markerFactory.NewMarker( aRefSeg, pad, padSeg, DRCE_TRACK_NEAR_PAD ) );
417 
418  if( !handleNewMarker() )
419  return false;
420  }
421  }
422  }
423 
424  /***********************************************/
425  /* Phase 2: test DRC with other track segments */
426  /***********************************************/
427 
428  // At this point the reference segment is the X axis
429 
430  // Test the reference segment with other track segments
431  wxPoint segStartPoint;
432  wxPoint segEndPoint;
433 
434  for( track = aStart; track; track = track->Next() )
435  {
436  // No problem if segments have the same net code:
437  if( net_code_ref == track->GetNetCode() )
438  continue;
439 
440  // No problem if segment are on different layers :
441  if( !( layerMask & track->GetLayerSet() ).any() )
442  continue;
443 
444  // the minimum distance = clearance plus half the reference track
445  // width plus half the other track's width
446  int w_dist = aRefSeg->GetClearance( track );
447  w_dist += ( aRefSeg->GetWidth() + track->GetWidth() ) / 2;
448 
449  // Due to many double to int conversions during calculations, which
450  // create rounding issues,
451  // the exact clearance margin cannot be really known.
452  // To avoid false bad DRC detection due to these rounding issues,
453  // slightly decrease the w_dist (remove one nanometer is enough !)
454  w_dist -= 1;
455 
456  // If the reference segment is a via, we test it here
457  if( aRefSeg->Type() == PCB_VIA_T )
458  {
459  delta = track->GetEnd() - track->GetStart();
460  segStartPoint = aRefSeg->GetStart() - track->GetStart();
461  wxPoint pos = aRefSeg->GetPosition();
462 
463  if( track->Type() == PCB_VIA_T )
464  {
465  // Test distance between two vias, i.e. two circles, trivial case
466  if( EuclideanNorm( segStartPoint ) < w_dist )
467  {
468  markers.push_back(
469  m_markerFactory.NewMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_VIA ) );
470 
471  if( !handleNewMarker() )
472  return false;
473  }
474  }
475  else // test via to segment
476  {
477  // Compute l'angle du segment a tester;
478  double angle = ArcTangente( delta.y, delta.x );
479 
480  // Compute new coordinates ( the segment become horizontal)
481  RotatePoint( &delta, angle );
482  RotatePoint( &segStartPoint, angle );
483 
484  if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
485  {
486  markers.push_back(
487  m_markerFactory.NewMarker( pos, aRefSeg, track, DRCE_VIA_NEAR_TRACK ) );
488 
489  if( !handleNewMarker() )
490  return false;
491  }
492  }
493 
494  continue;
495  }
496 
497  /* We compute segStartPoint, segEndPoint = starting and ending point coordinates for
498  * the segment to test in the new axis : the new X axis is the
499  * reference segment. We must translate and rotate the segment to test
500  */
501  segStartPoint = track->GetStart() - origin;
502  segEndPoint = track->GetEnd() - origin;
503  RotatePoint( &segStartPoint, m_segmAngle );
504  RotatePoint( &segEndPoint, m_segmAngle );
505 
506  SEG seg( segStartPoint, segEndPoint );
507 
508  if( track->Type() == PCB_VIA_T )
509  {
510  if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
511  continue;
512 
513  markers.push_back(
514  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_NEAR_VIA ) );
515 
516  if( !handleNewMarker() )
517  return false;
518  }
519 
520  /* We have changed axis:
521  * the reference segment is Horizontal.
522  * 3 cases : the segment to test can be parallel, perpendicular or have another direction
523  */
524  if( segStartPoint.y == segEndPoint.y ) // parallel segments
525  {
526  if( abs( segStartPoint.y ) >= w_dist )
527  continue;
528 
529  // Ensure segStartPoint.x <= segEndPoint.x
530  if( segStartPoint.x > segEndPoint.x )
531  std::swap( segStartPoint.x, segEndPoint.x );
532 
533  if( segStartPoint.x > ( -w_dist ) && segStartPoint.x < ( m_segmLength + w_dist ) )
534  {
535  // the start point is inside the reference range
536  // X........
537  // O--REF--+
538 
539  // Fine test : we consider the rounded shape of each end of the track segment:
540  if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
541  {
542  markers.push_back(
543  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS1 ) );
544 
545  if( !handleNewMarker() )
546  return false;
547  }
548 
549  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
550  {
551  markers.push_back(
552  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS2 ) );
553 
554  if( !handleNewMarker() )
555  return false;
556  }
557  }
558 
559  if( segEndPoint.x > ( -w_dist ) && segEndPoint.x < ( m_segmLength + w_dist ) )
560  {
561  // the end point is inside the reference range
562  // .....X
563  // O--REF--+
564  // Fine test : we consider the rounded shape of the ends
565  if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
566  {
567  markers.push_back(
568  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS3 ) );
569 
570  if( !handleNewMarker() )
571  return false;
572  }
573 
574  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
575  {
576  markers.push_back(
577  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACK_ENDS4 ) );
578 
579  if( !handleNewMarker() )
580  return false;
581  }
582  }
583 
584  if( segStartPoint.x <= 0 && segEndPoint.x >= 0 )
585  {
586  // the segment straddles the reference range (this actually only
587  // checks if it straddles the origin, because the other cases where already
588  // handled)
589  // X.............X
590  // O--REF--+
591  markers.push_back( m_markerFactory.NewMarker(
592  aRefSeg, track, seg, DRCE_TRACK_SEGMENTS_TOO_CLOSE ) );
593 
594  if( !handleNewMarker() )
595  return false;
596  }
597  }
598  else if( segStartPoint.x == segEndPoint.x ) // perpendicular segments
599  {
600  if( segStartPoint.x <= -w_dist || segStartPoint.x >= m_segmLength + w_dist )
601  continue;
602 
603  // Test if segments are crossing
604  if( segStartPoint.y > segEndPoint.y )
605  std::swap( segStartPoint.y, segEndPoint.y );
606 
607  if( ( segStartPoint.y < 0 ) && ( segEndPoint.y > 0 ) )
608  {
609  markers.push_back(
610  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_TRACKS_CROSSING ) );
611 
612  if( !handleNewMarker() )
613  return false;
614  }
615 
616  // At this point the drc error is due to an end near a reference segm end
617  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
618  {
619  markers.push_back(
620  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM1 ) );
621 
622  if( !handleNewMarker() )
623  return false;
624  }
625  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
626  {
627  markers.push_back(
628  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM2 ) );
629 
630  if( !handleNewMarker() )
631  return false;
632  }
633  }
634  else // segments quelconques entre eux
635  {
636  // calcul de la "surface de securite du segment de reference
637  // First rought 'and fast) test : the track segment is like a rectangle
638 
639  m_xcliplo = m_ycliplo = -w_dist;
640  m_xcliphi = m_segmLength + w_dist;
641  m_ycliphi = w_dist;
642 
643  // A fine test is needed because a serment is not exactly a
644  // rectangle, it has rounded ends
645  if( !checkLine( segStartPoint, segEndPoint ) )
646  {
647  /* 2eme passe : the track has rounded ends.
648  * we must a fine test for each rounded end and the
649  * rectangular zone
650  */
651 
652  m_xcliplo = 0;
654 
655  if( !checkLine( segStartPoint, segEndPoint ) )
656  {
657  markers.push_back(
658  m_markerFactory.NewMarker( aRefSeg, track, seg, DRCE_ENDS_PROBLEM3 ) );
659 
660  if( !handleNewMarker() )
661  return false;
662  }
663  else // The drc error is due to the starting or the ending point of the reference segment
664  {
665  // Test the starting and the ending point
666  segStartPoint = track->GetStart();
667  segEndPoint = track->GetEnd();
668  delta = segEndPoint - segStartPoint;
669 
670  // Compute the segment orientation (angle) en 0,1 degre
671  double angle = ArcTangente( delta.y, delta.x );
672 
673  // Compute the segment length: delta.x = length after rotation
674  RotatePoint( &delta, angle );
675 
676  /* Comute the reference segment coordinates relatives to a
677  * X axis = current tested segment
678  */
679  wxPoint relStartPos = aRefSeg->GetStart() - segStartPoint;
680  wxPoint relEndPos = aRefSeg->GetEnd() - segStartPoint;
681 
682  RotatePoint( &relStartPos, angle );
683  RotatePoint( &relEndPos, angle );
684 
685  if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
686  {
687  markers.push_back( m_markerFactory.NewMarker(
688  aRefSeg, track, seg, DRCE_ENDS_PROBLEM4 ) );
689 
690  if( !handleNewMarker() )
691  return false;
692  }
693 
694  if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
695  {
696  markers.push_back( m_markerFactory.NewMarker(
697  aRefSeg, track, seg, DRCE_ENDS_PROBLEM5 ) );
698 
699  if( !handleNewMarker() )
700  return false;
701  }
702  }
703  }
704  }
705  }
706 
707  /***********************************************/
708  /* Phase 3: test DRC with zones */
709  /***********************************************/
710 
711  SEG refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
712 
713  for( ZONE_CONTAINER* zone : m_pcb->Zones() )
714  {
715  if( zone->GetFilledPolysList().IsEmpty() || zone->GetIsKeepout() )
716  continue;
717 
718  if( !( layerMask & zone->GetLayerSet() ).any() )
719  continue;
720 
721  if( zone->GetNetCode() && zone->GetNetCode() == net_code_ref )
722  continue;
723 
724  int clearance = zone->GetClearance( aRefSeg );
725  SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
726 
727  if( outline->Distance( refSeg, aRefSeg->GetWidth() ) < clearance )
729  }
730 
731  /***********************************************/
732  /* Phase 4: test DRC with to board edge */
733  /***********************************************/
734  {
735  SEG test_seg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
736 
737  // the minimum distance = clearance plus half the reference track
738  // width. Board edges do not have width or clearance values, so we
739  // look for simple crossing.
740  SEG::ecoord w_dist = aRefSeg->GetClearance() + aRefSeg->GetWidth() / 2;
741  w_dist *= w_dist;
742 
743  for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
744  {
745  if( test_seg.SquaredDistance( *it ) < w_dist )
746  {
747  auto pt = test_seg.NearestPoint( *it );
748  markers.push_back( m_markerFactory.NewMarker(
749  wxPoint( pt.x, pt.y ), aRefSeg, DRCE_TRACK_NEAR_EDGE ) );
750 
751  if( !handleNewMarker() )
752  return false;
753  }
754  }
755  }
756 
757 
758  if( markers.size() > 0 )
759  {
760  commitMarkers();
761  return false;
762  }
763  else
764  return true;
765 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
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_TOO_SMALL_MICROVIA_DRILL
Too small micro via drill.
Definition: drc.h:78
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
#define DRCE_TOO_SMALL_VIA
Too small via size.
Definition: drc.h:75
int GetNetCode() const
Function GetNetCode.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
int m_ycliplo
Definition: drc.h:222
const wxPoint & GetStart() const
Definition: class_track.h:126
VECTOR2I::extended_type ecoord
Definition: seg.h:39
#define DRCE_TRACK_ENDS4
2 parallel track segments too close: fine end point test
Definition: drc.h:58
int m_ycliphi
Definition: drc.h:224
#define DRCE_TRACK_NEAR_PAD
pad too close to track
Definition: drc.h:51
int m_segmLength
Definition: drc.h:216
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
wxPoint m_padToTestPos
Definition: drc.h:207
#define abs(a)
Definition: auxiliary.h:84
static const int delta[8][2]
Definition: solve.cpp:112
#define DRCE_TRACK_ENDS2
2 parallel track segments too close: fine start point test
Definition: drc.h:56
#define DRCE_TRACK_SEGMENTS_TOO_CLOSE
2 parallel track segments too close: segm ends between segref ends
Definition: drc.h:59
#define DRCE_BURIED_VIA_NOT_ALLOWED
buried vias are not allowed
Definition: drc.h:97
#define DRCE_TRACK_NEAR_VIA
track too close to via
Definition: drc.h:52
BOARD * m_pcb
Definition: drc.h:227
#define DRCE_TOO_SMALL_MICROVIA
Too small micro via size.
Definition: drc.h:76
bool checkLine(wxPoint aSegStart, wxPoint aSegEnd)
Function checkLine (helper function used in drc calculations to see if one track is in contact with a...
#define DRCE_VIA_HOLE_BIGGER
via's hole is bigger than its diameter
Definition: drc.h:67
PCB_LAYER_ID
A quick note on layer IDs:
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint GetPosition() const override
Definition: class_track.h:117
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:170
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
#define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR
micro via's layer pair incorrect (layers must be adjacent)
Definition: drc.h:68
Class SHAPE_POLY_SET.
int m_TrackMinWidth
track min value for width ((min copper size value
#define DRCE_TRACK_ENDS1
2 parallel track segments too close: fine start point test
Definition: drc.h:55
int m_ViasMinSize
vias (not micro vias) min diameter
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
#define DRCE_TRACK_ENDS3
2 parallel track segments too close: fine end point test
Definition: drc.h:57
#define DRCE_ENDS_PROBLEM2
track ends are too close
Definition: drc.h:62
int m_ViasMinDrill
vias (not micro vias) min drill diameter
#define DRCE_TRACK_NEAR_ZONE
track & zone collide or are too close together
Definition: drc.h:91
#define DRCE_ENDS_PROBLEM3
track ends are too close
Definition: drc.h:63
VIATYPE_T GetViaType() const
Definition: class_track.h:461
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Check the distance from a point to a segment.
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
bool m_reportAllTrackErrors
Definition: drc.h:189
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc.h:223
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:226
string & err
Definition: json11.cpp:598
const wxPoint GetPosition() const override
Definition: class_track.h:433
unsigned GetPadCount()
Function GetPadCount.
#define DRCE_ENDS_PROBLEM4
track ends are too close
Definition: drc.h:64
Definition: seg.h:36
#define DRCE_VIA_NEAR_VIA
via too close to via
Definition: drc.h:53
#define DRCE_TRACKS_CROSSING
tracks are crossing
Definition: drc.h:60
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Check the distance from a pad to segment.
#define DRCE_ENDS_PROBLEM5
track ends are too close
Definition: drc.h:65
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
wxPoint m_segmEnd
Definition: drc.h:208
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:228
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
int GetWidth() const
Definition: class_track.h:120
TRACK * Next() const
Definition: class_track.h:103
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:389
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
wxPoint ShapePos() const
Definition: class_pad.cpp:550
#define DRCE_VIA_NEAR_TRACK
via too close to track
Definition: drc.h:54
const wxPoint & GetEnd() const
Definition: class_track.h:123
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
#define DRCE_TRACK_NEAR_EDGE
track too close to board edge
Definition: drc.h:100
bool m_MicroViasAllowed
true to allow micro vias
#define DRCE_MICRO_VIA_NOT_ALLOWED
micro vias are not allowed
Definition: drc.h:96
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
const wxPoint GetPosition() const override
Definition: class_pad.h:220
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201
int m_xcliplo
Definition: drc.h:221
int GetCopperLayerCount() const
Function GetCopperLayerCount.
#define DRCE_ENDS_PROBLEM1
track ends are too close
Definition: drc.h:61
#define DRCE_TOO_SMALL_VIA_DRILL
Too small via drill.
Definition: drc.h:77
#define DRCE_TRACK_NEAR_THROUGH_HOLE
thru hole is too close to track
Definition: drc.h:50
double m_segmAngle
Definition: drc.h:215
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.
#define DRCE_TOO_SMALL_TRACK_WIDTH
Too small track width.
Definition: drc.h:74

References abs, COMMIT::Add(), addMarkerToPcb(), LSET::AllCuMask(), PNS::angle(), ArcTangente(), B_Cu, checkClearanceSegmToPad(), checkLine(), checkMarginToCircle(), delta, SHAPE_POLY_SET::Distance(), DRCE_BURIED_VIA_NOT_ALLOWED, DRCE_ENDS_PROBLEM1, DRCE_ENDS_PROBLEM2, DRCE_ENDS_PROBLEM3, DRCE_ENDS_PROBLEM4, DRCE_ENDS_PROBLEM5, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR, DRCE_MICRO_VIA_NOT_ALLOWED, DRCE_TOO_SMALL_MICROVIA, DRCE_TOO_SMALL_MICROVIA_DRILL, DRCE_TOO_SMALL_TRACK_WIDTH, DRCE_TOO_SMALL_VIA, DRCE_TOO_SMALL_VIA_DRILL, DRCE_TRACK_ENDS1, DRCE_TRACK_ENDS2, DRCE_TRACK_ENDS3, DRCE_TRACK_ENDS4, DRCE_TRACK_NEAR_EDGE, DRCE_TRACK_NEAR_PAD, DRCE_TRACK_NEAR_THROUGH_HOLE, DRCE_TRACK_NEAR_VIA, DRCE_TRACK_NEAR_ZONE, DRCE_TRACK_SEGMENTS_TOO_CLOSE, DRCE_TRACKS_CROSSING, DRCE_VIA_HOLE_BIGGER, DRCE_VIA_NEAR_TRACK, DRCE_VIA_NEAR_VIA, err, EuclideanNorm(), F_Cu, TRACK::GetClearance(), BOARD_DESIGN_SETTINGS::GetCopperLayerCount(), BOARD::GetDesignSettings(), D_PAD::GetDrillShape(), D_PAD::GetDrillSize(), VIA::GetDrillValue(), TRACK::GetEnd(), BOARD_ITEM::GetLayerSet(), D_PAD::GetLayerSet(), BOARD_CONNECTED_ITEM::GetNetClass(), BOARD_CONNECTED_ITEM::GetNetCode(), D_PAD::GetOrientation(), BOARD::GetPadCount(), BOARD::GetPads(), TRACK::GetPosition(), D_PAD::GetPosition(), VIA::GetPosition(), TRACK::GetStart(), VIA::GetViaType(), TRACK::GetWidth(), In1_Cu, SHAPE_POLY_SET::IterateSegmentsWithHoles(), VIA::LayerPair(), BOARD_DESIGN_SETTINGS::m_BlindBuriedViaAllowed, m_board_outlines, m_drcInLegacyRoutingMode, m_markerFactory, BOARD_DESIGN_SETTINGS::m_MicroViasAllowed, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, m_padToTestPos, m_pcb, m_pcbEditorFrame, m_reportAllTrackErrors, m_segmAngle, m_segmEnd, m_segmLength, BOARD_DESIGN_SETTINGS::m_TrackMinWidth, BOARD_DESIGN_SETTINGS::m_ViasMinDrill, BOARD_DESIGN_SETTINGS::m_ViasMinSize, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, DRC_MARKER_FACTORY::NewMarker(), TRACK::Next(), PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PCB_VIA_T, BOARD_COMMIT::Push(), RotatePoint(), D_PAD::SetLayerSet(), EDA_DRAW_FRAME::SetMsgPanel(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), D_PAD::SetSize(), D_PAD::ShapePos(), EDA_ITEM::Type(), VIA_BLIND_BURIED, VIA_MICROVIA, and BOARD::Zones().

Referenced by DrcOnCreatingTrack(), and testTracks().

◆ doTrackKeepoutDrc()

bool DRC::doTrackKeepoutDrc ( TRACK aRefSeg)
private

Test the current segment or via.

Parameters
aRefSegThe segment to test
Returns
bool - true if no problems, else false and m_currentMarker is filled in with the problem information.

Definition at line 1260 of file drc.cpp.

1261 {
1262  // Test keepout areas for vias, tracks and pads inside keepout areas
1263  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
1264  {
1265  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
1266 
1267  if( !area->GetIsKeepout() )
1268  continue;
1269 
1270  if( aRefSeg->Type() == PCB_TRACE_T )
1271  {
1272  if( !area->GetDoNotAllowTracks() )
1273  continue;
1274 
1275  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
1276  continue;
1277 
1278  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
1279  aRefSeg->GetWidth() ) == 0 )
1280  {
1281  m_currentMarker =
1283  return false;
1284  }
1285  }
1286  else if( aRefSeg->Type() == PCB_VIA_T )
1287  {
1288  if( !area->GetDoNotAllowVias() )
1289  continue;
1290 
1291  auto viaLayers = aRefSeg->GetLayerSet();
1292 
1293  if( !area->CommonLayerExists( viaLayers ) )
1294  continue;
1295 
1296  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1297  {
1298  m_currentMarker =
1300  return false;
1301  }
1302  }
1303  }
1304 
1305  return true;
1306 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
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
const wxPoint & GetStart() const
Definition: class_track.h:126
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
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:234
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:85
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:227
bool GetDoNotAllowVias() const
Definition: class_zone.h:623
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
const wxPoint GetPosition() const override
Definition: class_track.h:117
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:621
MARKER_PCB * m_currentMarker
Definition: drc.h:193
Definition: seg.h:36
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...
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc.h:86
const wxPoint & GetEnd() const
Definition: class_track.h:123
bool GetDoNotAllowTracks() const
Definition: class_zone.h:624
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
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

References ZONE_CONTAINER::CommonLayerExists(), SHAPE_POLY_SET::Distance(), DRCE_TRACK_INSIDE_KEEPOUT, DRCE_VIA_INSIDE_KEEPOUT, BOARD::GetArea(), BOARD::GetAreaCount(), ZONE_CONTAINER::GetDoNotAllowTracks(), ZONE_CONTAINER::GetDoNotAllowVias(), TRACK::GetEnd(), ZONE_CONTAINER::GetIsKeepout(), BOARD_ITEM::GetLayer(), BOARD_ITEM::GetLayerSet(), TRACK::GetPosition(), TRACK::GetStart(), TRACK::GetWidth(), ZONE_CONTAINER::IsOnLayer(), m_currentMarker, m_markerFactory, m_pcb, DRC_MARKER_FACTORY::NewMarker(), ZONE_CONTAINER::Outline(), PCB_TRACE_T, PCB_VIA_T, and EDA_ITEM::Type().

Referenced by DrcOnCreatingTrack().

◆ DrcOnCreatingTrack()

int DRC::DrcOnCreatingTrack ( TRACK aRefSeg,
TRACK aList 
)

Function Drc tests the current segment and returns the result and displays the error in the status panel only if one exists.

No marker created or added to the board. Must be used only during track creation in legacy canvas

Parameters
aRefSegThe current segment to test.
aListThe track list to test (usually m_Pcb->m_Track)
Returns
int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK

Definition at line 173 of file drc.cpp.

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  if( !doTrackDrc( aRefSegm, aList, true ) )
184  {
185  if( m_currentMarker )
186  {
188  delete m_currentMarker;
189  m_currentMarker = nullptr;
190  }
191 
192  m_drcInLegacyRoutingMode = drc_state;
193  m_reportAllTrackErrors = rpt_state;
194  return BAD_DRC;
195  }
196 
197  if( !doTrackKeepoutDrc( aRefSegm ) )
198  {
199  if( m_currentMarker )
200  {
202  delete m_currentMarker;
203  m_currentMarker = nullptr;
204  }
205 
206  m_drcInLegacyRoutingMode = drc_state;
207  m_reportAllTrackErrors = rpt_state;
208  return BAD_DRC;
209  }
210 
211  m_drcInLegacyRoutingMode = drc_state;
212  m_reportAllTrackErrors = rpt_state;
213  return OK_DRC;
214 }
#define OK_DRC
Definition: drc.h:39
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:1260
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:560
bool m_reportAllTrackErrors
Definition: drc.h:189
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
#define BAD_DRC
Definition: drc.h:40
MARKER_PCB * m_currentMarker
Definition: drc.h:193
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201

References BAD_DRC, doTrackDrc(), doTrackKeepoutDrc(), m_currentMarker, m_drcInLegacyRoutingMode, m_pcbEditorFrame, m_reportAllTrackErrors, OK_DRC, EDA_DRAW_FRAME::SetMsgPanel(), and updatePointers().

Referenced by PCB_EDIT_FRAME::Add45DegreeSegment(), PCB_EDIT_FRAME::Begin_Route(), PCB_EDIT_FRAME::End_Route(), PCB_EDIT_FRAME::Other_Layer_Route(), PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment(), and PCB_EDIT_FRAME::SetTrackSegmentWidth().

◆ DrcOnCreatingZone()

int DRC::DrcOnCreatingZone ( ZONE_CONTAINER aArea,
int  aCornerIndex 
)

Function Drc tests the outline segment starting at CornerIndex and returns the result and displays the error in the status panel only if one exists.

Test Edge inside other areas Test Edge too close other areas No marker created or added to the board. Must be used only during zone creation in legacy canvas

Parameters
aAreaThe area parent which contains the corner.
aCornerIndexThe starting point of the segment to test.
Returns
int - BAD_DRC (1) if DRC error or OK_DRC (0) if OK

Definition at line 370 of file drc.cpp.

371 {
372  updatePointers();
373 
374  // Set right options for this on line drc
375  int drc_state = m_drcInLegacyRoutingMode;
377  int rpt_state = m_reportAllTrackErrors;
378  m_reportAllTrackErrors = false;
379 
380  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
381  {
382  wxASSERT( m_currentMarker );
384  delete m_currentMarker;
385  m_currentMarker = nullptr;
386  m_drcInLegacyRoutingMode = drc_state;
387  m_reportAllTrackErrors = rpt_state;
388  return BAD_DRC;
389  }
390 
391  m_drcInLegacyRoutingMode = drc_state;
392  m_reportAllTrackErrors = rpt_state;
393  return OK_DRC;
394 }
#define OK_DRC
Definition: drc.h:39
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Clear the message panel and populates it with the contents of aList.
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:560
bool m_reportAllTrackErrors
Definition: drc.h:189
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
#define BAD_DRC
Definition: drc.h:40
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...
MARKER_PCB * m_currentMarker
Definition: drc.h:193
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201

References BAD_DRC, doEdgeZoneDrc(), m_currentMarker, m_drcInLegacyRoutingMode, m_pcbEditorFrame, m_reportAllTrackErrors, OK_DRC, EDA_DRAW_FRAME::SetMsgPanel(), and updatePointers().

Referenced by PCB_EDIT_FRAME::Begin_Zone(), and PCB_EDIT_FRAME::End_Zone().

◆ GetCurrentMarker()

MARKER_PCB* DRC::GetCurrentMarker ( )
inline
Returns
a pointer to the current marker (last created marker

Definition at line 515 of file drc.h.

516  {
517  return m_currentMarker;
518  }
MARKER_PCB * m_currentMarker
Definition: drc.h:193

References m_currentMarker.

Referenced by PCB_EDIT_FRAME::Other_Layer_Route().

◆ ListUnconnectedPads()

void DRC::ListUnconnectedPads ( )

Gather a list of all the unconnected pads and shows them in the dialog, and optionally prints a report of such.

Definition at line 551 of file drc.cpp.

552 {
553  testUnconnected();
554 
555  // update the m_drcDialog listboxes
556  updatePointers();
557 }
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:560
void testUnconnected()
Definition: drc.cpp:861

References testUnconnected(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick().

◆ RunTests()

void DRC::RunTests ( wxTextCtrl *  aMessages = NULL)

Run all the tests specified with a previous call to SetSettings()

Parameters
aMessages= a wxTextControl where to display some activity messages. Can be NULL

Definition at line 397 of file drc.cpp.

398 {
399  // be sure m_pcb is the current board, not a old one
400  // ( the board can be reloaded )
402 
403  if( aMessages )
404  {
405  aMessages->AppendText( _( "Board Outline...\n" ) );
406  wxSafeYield();
407  }
408 
409  testOutline();
410 
411  // someone should have cleared the two lists before calling this.
412  if( !testNetClasses() )
413  {
414  // testing the netclasses is a special case because if the netclasses
415  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
416  // class (a NET) will cause its items such as tracks, vias, and pads
417  // to also fail. So quit after *all* netclass errors have been reported.
418  if( aMessages )
419  aMessages->AppendText( _( "Aborting\n" ) );
420 
421  // update the m_drcDialog listboxes
422  updatePointers();
423 
424  return;
425  }
426 
427  // test pad to pad clearances, nothing to do with tracks, vias or zones.
428  if( m_doPad2PadTest )
429  {
430  if( aMessages )
431  {
432  aMessages->AppendText( _( "Pad clearances...\n" ) );
433  wxSafeYield();
434  }
435 
436  testPad2Pad();
437  }
438 
439  // test clearances between drilled holes
440  if( aMessages )
441  {
442  aMessages->AppendText( _( "Drill clearances...\n" ) );
443  wxSafeYield();
444  }
445 
447 
448  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
449  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
450 
451  if( m_refillZones )
452  {
453  if( aMessages )
454  aMessages->AppendText( _( "Refilling all zones...\n" ) );
455 
456  m_pcbEditorFrame->Fill_All_Zones( caller );
457  }
458  else
459  {
460  if( aMessages )
461  aMessages->AppendText( _( "Checking zone fills...\n" ) );
462 
464  }
465 
466  // test track and via clearances to other tracks, pads, and vias
467  if( aMessages )
468  {
469  aMessages->AppendText( _( "Track clearances...\n" ) );
470  wxSafeYield();
471  }
472 
473  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
474 
475  // test zone clearances to other zones
476  if( aMessages )
477  {
478  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
479  wxSafeYield();
480  }
481 
482  testZones();
483 
484  // find and gather unconnected pads.
485  if( m_doUnconnectedTest )
486  {
487  if( aMessages )
488  {
489  aMessages->AppendText( _( "Unconnected pads...\n" ) );
490  aMessages->Refresh();
491  }
492 
493  testUnconnected();
494  }
495 
496  // find and gather vias, tracks, pads inside keepout areas.
497  if( m_doKeepoutTest )
498  {
499  if( aMessages )
500  {
501  aMessages->AppendText( _( "Keepout areas ...\n" ) );
502  aMessages->Refresh();
503  }
504 
506  }
507 
508  // find and gather vias, tracks, pads inside text boxes.
509  if( aMessages )
510  {
511  aMessages->AppendText( _( "Test texts...\n" ) );
512  wxSafeYield();
513  }
514 
516 
517  // find overlapping courtyard ares.
520  {
521  if( aMessages )
522  {
523  aMessages->AppendText( _( "Courtyard areas...\n" ) );
524  aMessages->Refresh();
525  }
526 
528  }
529 
530  // Check if there are items on disabled layers
532 
533  if( aMessages )
534  {
535  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
536  aMessages->Refresh();
537  }
538 
539  // update the m_drcDialog listboxes
540  updatePointers();
541 
542  if( aMessages )
543  {
544  // no newline on this one because it is last, don't want the window
545  // to unnecessarily scroll.
546  aMessages->AppendText( _( "Finished" ) );
547  }
548 }
bool m_refillZones
Definition: drc.h:188
void testCopperTextAndGraphics()
Definition: drc.cpp:974
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
void testKeepoutAreas()
Definition: drc.cpp:925
void Check_All_Zones(wxWindow *aActiveWindow)
Function Check_All_Zones Checks for out-of-date fills and fills them if requested by the user.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
Definition: drc.cpp:1211
BOARD * m_pcb
Definition: drc.h:227
void testDrilledHoles()
Definition: drc.cpp:729
bool m_doKeepoutTest
Definition: drc.h:186
void testZones()
Definition: drc.cpp:889
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:560
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
Definition: drc.cpp:1223
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
bool m_doPad2PadTest
Definition: drc.h:183
void testPad2Pad()
Definition: drc.cpp:685
bool m_RequireCourtyards
require courtyard definitions in footprints
bool testNetClasses()
Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance ...
Definition: drc.cpp:662
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
Definition: drc.cpp:802
int Fill_All_Zones(wxWindow *aActiveWindow)
Function Fill_All_Zones Fill all zones on the board The old fillings are removed.
BOARD * GetBoard() const
void testUnconnected()
Definition: drc.cpp:861
bool m_doUnconnectedTest
Definition: drc.h:184
void doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1441

References PCB_EDIT_FRAME::Check_All_Zones(), doFootprintOverlappingDrc(), PCB_EDIT_FRAME::Fill_All_Zones(), PCB_BASE_FRAME::GetBoard(), BOARD::GetDesignSettings(), m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_pcb, m_pcbEditorFrame, BOARD_DESIGN_SETTINGS::m_ProhibitOverlappingCourtyards, m_refillZones, BOARD_DESIGN_SETTINGS::m_RequireCourtyards, testCopperTextAndGraphics(), testDisabledLayers(), testDrilledHoles(), testKeepoutAreas(), testNetClasses(), testOutline(), testPad2Pad(), testTracks(), testUnconnected(), testZones(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnStartdrcClick().

◆ SetSettings()

void DRC::SetSettings ( bool  aPad2PadTest,
bool  aUnconnectedTest,
bool  aZonesTest,
bool  aKeepoutTest,
bool  aRefillZones,
bool  aReportAllTrackErrors,
const wxString &  aReportName,
bool  aSaveReport 
)
inline

Save all the UI or test settings and may be called before running the tests.

Parameters
aPad2PadTestTells whether to test pad to pad distances.
aUnconnectedTestTells whether to list unconnected pads.
aZonesTestTells whether to test zones.
aRefillZonesRefill zones before performing DRC.
aKeepoutTestTells whether to test keepout areas.
aReportAllTrackErrorsTells whether or not to stop checking track connections after the first error.
aReportNameA string telling the disk file report name entered.
aSaveReportA boolean telling whether to generate disk file report.

Definition at line 482 of file drc.h.

486  {
487  m_doPad2PadTest = aPad2PadTest;
488  m_doUnconnectedTest = aUnconnectedTest;
489  m_doZonesTest = aZonesTest;
490  m_doKeepoutTest = aKeepoutTest;
491  m_rptFilename = aReportName;
492  m_doCreateRptFile = aSaveReport;
493  m_refillZones = aRefillZones;
494  m_drcInLegacyRoutingMode = false;
495  m_reportAllTrackErrors = aReportAllTrackErrors;
496  }
bool m_refillZones
Definition: drc.h:188
bool m_doCreateRptFile
Definition: drc.h:187
bool m_doKeepoutTest
Definition: drc.h:186
bool m_doZonesTest
Definition: drc.h:185
bool m_reportAllTrackErrors
Definition: drc.h:189
bool m_doPad2PadTest
Definition: drc.h:183
wxString m_rptFilename
Definition: drc.h:191
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:201
bool m_doUnconnectedTest
Definition: drc.h:184

References m_doCreateRptFile, m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_doZonesTest, m_drcInLegacyRoutingMode, m_refillZones, m_reportAllTrackErrors, and m_rptFilename.

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick(), and DIALOG_DRC_CONTROL::OnStartdrcClick().

◆ ShowDRCDialog()

void DRC::ShowDRCDialog ( wxWindow *  aParent = NULL)

Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and creates the MARKERS.

The dialog is only created if it is not already in existence.

Parameters
aParentis the parent window for wxWidgets. Usually the PCB editor frame but can be another dialog if aParent == NULL (default), the parent will be the PCB editor frame and the dialog will be not modal (just float on parent if aParent is specified, the dialog will be modal. The modal mode is mandatory if the dialog is created from another dialog, not from the PCB editor frame

Definition at line 63 of file drc.cpp.

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 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool m_doCreateRptFile
Definition: drc.h:187
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:229
static TOOL_ACTION cancelInteractive
Definition: actions.h:45
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
void DeactivateTool()
Function DeactivateTool() Deactivates the currently active tool.
TOOL_MANAGER * GetToolManager() const
Return the tool manager instance, if any.
Definition: draw_frame.h:941
Class TOOL_MANAGER.
Definition: tool_manager.h:49
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:560
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
bool Show(bool show) override
friend class DIALOG_DRC_CONTROL
Definition: drc.h:178
wxString m_rptFilename
Definition: drc.h:191
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:177

References ACTIONS::cancelInteractive, TOOL_MANAGER::DeactivateTool(), DIALOG_DRC_CONTROL, EDA_DRAW_FRAME::GetToolManager(), m_doCreateRptFile, m_drcDialog, m_pcbEditorFrame, m_rptFilename, TOOL_MANAGER::RunAction(), PCB_ACTIONS::selectionClear, DIALOG_DRC_CONTROL::SetRptSettings(), DIALOG_SHIM::Show(), and updatePointers().

Referenced by DIALOG_PLOT::onRunDRC(), and PCB_EDIT_FRAME::Process_Special_Functions().

◆ testCopperDrawItem()

void DRC::testCopperDrawItem ( DRAWSEGMENT aDrawing)
private

Definition at line 1017 of file drc.cpp.

1018 {
1019  std::vector<SEG> itemShape;
1020  int itemWidth = aItem->GetWidth();
1021 
1022  switch( aItem->GetShape() )
1023  {
1024  case S_ARC:
1025  {
1026  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
1027 
1028  auto l = arc.ConvertToPolyline();
1029 
1030  for( int i = 0; i < l.SegmentCount(); i++ )
1031  itemShape.push_back( l.CSegment(i) );
1032 
1033  break;
1034  }
1035 
1036  case S_SEGMENT:
1037  itemShape.push_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
1038  break;
1039 
1040  case S_CIRCLE:
1041  {
1042  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
1043  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1044 
1045  auto l = circle.ConvertToPolyline();
1046 
1047  for( int i = 0; i < l.SegmentCount(); i++ )
1048  itemShape.push_back( l.CSegment(i) );
1049 
1050  break;
1051  }
1052 
1053  case S_CURVE:
1054  {
1055  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1056  wxPoint start_pt = aItem->GetBezierPoints()[0];
1057 
1058  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1059  {
1060  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1061  itemShape.push_back( SEG( start_pt, end_pt ) );
1062  start_pt = end_pt;
1063  }
1064 
1065  break;
1066  }
1067 
1068  default:
1069  break;
1070  }
1071 
1072  // Test tracks and vias
1073  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1074  {
1075  if( !track->IsOnLayer( aItem->GetLayer() ) )
1076  continue;
1077 
1078  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1079  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1080 
1081  for( const auto& itemSeg : itemShape )
1082  {
1083  if( trackAsSeg.Distance( itemSeg ) < minDist )
1084  {
1085  if( track->Type() == PCB_VIA_T )
1087  track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1088  else
1090  track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1091  break;
1092  }
1093  }
1094  }
1095 
1096  // Test pads
1097  for( auto pad : m_pcb->GetPads() )
1098  {
1099  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1100  continue;
1101 
1102  // Graphic items are allowed to act as net-ties within their own footprint
1103  if( pad->GetParent() == aItem->GetParent() )
1104  continue;
1105 
1106  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1107  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1108  SHAPE_POLY_SET padOutline;
1109 
1110  // We incorporate "minDist" into the pad's outline
1111  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ),
1112  segmentCount, correctionFactor );
1113 
1114  for( const auto& itemSeg : itemShape )
1115  {
1116  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1117  {
1119  break;
1120  }
1121  }
1122  }
1123 }
usual segment : line with rounded ends
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:89
BOARD * m_pcb
Definition: drc.h:227
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:88
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
Class SHAPE_POLY_SET.
Arcs (with rounded ends)
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
Bezier Curve.
Definition: seg.h:36
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
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
#define DRCE_PAD_NEAR_COPPER
pad and copper graphic collide or are too close
Definition: drc.h:90
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
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
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)

References addMarkerToPcb(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF, SHAPE_ARC::ConvertToPolyline(), SHAPE_POLY_SET::Distance(), DRCE_PAD_NEAR_COPPER, DRCE_TRACK_NEAR_COPPER, DRCE_VIA_NEAR_COPPER, DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetBezierPoints(), DRAWSEGMENT::GetCenter(), GetCircletoPolyCorrectionFactor(), DRAWSEGMENT::GetEnd(), BOARD_ITEM::GetLayer(), BOARD::GetPads(), BOARD_ITEM::GetParent(), DRAWSEGMENT::GetShape(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), i, m_markerFactory, m_pcb, BOARD::m_Track, DRC_MARKER_FACTORY::NewMarker(), PCB_VIA_T, DRAWSEGMENT::RebuildBezierToSegmentsPointsList(), S_ARC, S_CIRCLE, S_CURVE, and S_SEGMENT.

Referenced by testCopperTextAndGraphics().

◆ testCopperTextAndGraphics()

void DRC::testCopperTextAndGraphics ( )
private

Definition at line 974 of file drc.cpp.

975 {
976  // Test copper items for clearance violations with vias, tracks and pads
977 
978  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
979  {
980  if( IsCopperLayer( brdItem->GetLayer() ) )
981  {
982  if( brdItem->Type() == PCB_TEXT_T )
983  testCopperTextItem( brdItem );
984  else if( brdItem->Type() == PCB_LINE_T )
985  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
986  }
987  }
988 
989  for( MODULE* module : m_pcb->Modules() )
990  {
991  TEXTE_MODULE& ref = module->Reference();
992  TEXTE_MODULE& val = module->Value();
993 
994  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
995  testCopperTextItem( &ref );
996 
997  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
998  testCopperTextItem( &val );
999 
1000  if( module->IsNetTie() )
1001  continue;
1002 
1003  for( BOARD_ITEM* item = module->GraphicalItemsList(); item; item = item->Next() )
1004  {
1005  if( IsCopperLayer( item->GetLayer() ) )
1006  {
1007  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
1008  testCopperTextItem( item );
1009  else if( item->Type() == PCB_MODULE_EDGE_T )
1010  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
1011  }
1012  }
1013  }
1014 }
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
bool IsVisible() const
Definition: eda_text.h:189
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
Definition: drc.cpp:1017
void testCopperTextItem(BOARD_ITEM *aTextItem)
Definition: drc.cpp:1126
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
BOARD * m_pcb
Definition: drc.h:227
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
BOARD_ITEM * Next() const
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256

References BOARD::Drawings(), BOARD_ITEM::GetLayer(), IsCopperLayer(), EDA_TEXT::IsVisible(), m_pcb, BOARD::Modules(), BOARD_ITEM::Next(), PCB_LINE_T, PCB_MODULE_EDGE_T, PCB_MODULE_TEXT_T, PCB_TEXT_T, testCopperDrawItem(), and testCopperTextItem().

Referenced by RunTests().

◆ testCopperTextItem()

void DRC::testCopperTextItem ( BOARD_ITEM aTextItem)
private

Definition at line 1126 of file drc.cpp.

1127 {
1128  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1129 
1130  if( text == nullptr )
1131  return;
1132 
1133  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1134  int textWidth = text->GetThickness();
1135 
1136  // So far the bounding box makes up the text-area
1137  text->TransformTextShapeToSegmentList( textShape );
1138 
1139  if( textShape.size() == 0 ) // Should not happen (empty text?)
1140  return;
1141 
1142  EDA_RECT bbox = text->GetTextBox();
1143  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1144 
1145  // Test tracks and vias
1146  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1147  {
1148  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1149  continue;
1150 
1151  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1152  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1153 
1154  // Fast test to detect a trach segment candidate inside the text bounding box
1155  if( !rect_area.Collide( trackAsSeg, minDist ) )
1156  continue;
1157 
1158  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1159  {
1160  SEG textSeg( textShape[jj], textShape[jj+1] );
1161 
1162  if( trackAsSeg.Distance( textSeg ) < minDist )
1163  {
1164  if( track->Type() == PCB_VIA_T )
1166  track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1167  else
1169  track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
1170  break;
1171  }
1172  }
1173  }
1174 
1175  // Test pads
1176  for( auto pad : m_pcb->GetPads() )
1177  {
1178  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1179  continue;
1180 
1181  // Fast test to detect a pad candidate inside the text bounding box
1182  // Finer test (time consumming) is made only for pads near the text.
1183  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1184  VECTOR2I shape_pos( pad->ShapePos() );
1185 
1186  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1187  continue;
1188 
1189  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1190  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1191  SHAPE_POLY_SET padOutline;
1192 
1193  int minDist = textWidth/2 + pad->GetClearance( NULL );
1194  pad->TransformShapeWithClearanceToPolygon( padOutline, 0,
1195  segmentCount, correctionFactor );
1196 
1197  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1198  {
1199  SEG textSeg( textShape[jj], textShape[jj+1] );
1200 
1201  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1202  {
1204  break;
1205  }
1206  }
1207  }
1208 }
int GetX() const
Definition: eda_rect.h:109
int GetWidth() const
Definition: eda_rect.h:117
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:167
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:89
BOARD * m_pcb
Definition: drc.h:227
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:127
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:88
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
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
Class SHAPE_POLY_SET.
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
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
int GetHeight() const
Definition: eda_rect.h:118
Definition: seg.h:36
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
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
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
#define ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF
Definition: pcbnew.h:42
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)

References addMarkerToPcb(), ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF, SHAPE_POLY_SET::Distance(), DRCE_PAD_NEAR_COPPER, DRCE_TRACK_NEAR_COPPER, DRCE_VIA_NEAR_COPPER, GetCircletoPolyCorrectionFactor(), EDA_RECT::GetHeight(), BOARD_ITEM::GetLayer(), BOARD::GetPads(), EDA_TEXT::GetTextBox(), EDA_TEXT::GetThickness(), EDA_RECT::GetWidth(), EDA_RECT::GetX(), EDA_RECT::GetY(), m_markerFactory, m_pcb, BOARD::m_Track, DRC_MARKER_FACTORY::NewMarker(), PCB_VIA_T, and EDA_TEXT::TransformTextShapeToSegmentList().

Referenced by testCopperTextAndGraphics().

◆ testDisabledLayers()

void DRC::testDisabledLayers ( )
private

Tests for items placed on disabled layers (causing false connections).

Definition at line 1223 of file drc.cpp.

1224 {
1225  BOARD* board = m_pcbEditorFrame->GetBoard();
1226  wxCHECK( board, /*void*/ );
1227  LSET disabledLayers = board->GetEnabledLayers().flip();
1228 
1229  // Perform the test only for copper layers
1230  disabledLayers &= LSET::AllCuMask();
1231 
1232  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1234  aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1235  };
1236 
1237  for( auto track : board->Tracks() )
1238  {
1239  if( disabledLayers.test( track->GetLayer() ) )
1240  createMarker( track );
1241  }
1242 
1243  for( auto module : board->Modules() )
1244  {
1245  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1246  {
1247  if( disabledLayers.test( aItem->GetLayer() ) )
1248  createMarker( aItem );
1249  } );
1250  }
1251 
1252  for( auto zone : board->Zones() )
1253  {
1254  if( disabledLayers.test( zone->GetLayer() ) )
1255  createMarker( zone );
1256  }
1257 }
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
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
Class LSET is a set of PCB_LAYER_IDs.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
BOARD * GetBoard() const
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.

References addMarkerToPcb(), LSET::AllCuMask(), DRCE_DISABLED_LAYER_ITEM, PCB_BASE_FRAME::GetBoard(), BOARD::GetEnabledLayers(), BOARD_ITEM::GetLayer(), m_markerFactory, m_pcbEditorFrame, BOARD::Modules(), DRC_MARKER_FACTORY::NewMarker(), BOARD::Tracks(), and BOARD::Zones().

Referenced by RunTests().

◆ testDrilledHoles()

void DRC::testDrilledHoles ( )
private

Definition at line 729 of file drc.cpp.

730 {
731  int holeToHoleMin = m_pcb->GetDesignSettings().m_HoleToHoleMin;
732 
733  if( holeToHoleMin == 0 ) // No min setting turns testing off.
734  return;
735 
736  // Test drilled hole clearances to minimize drill bit breakage.
737  //
738  // Notes: slots are milled, so we're only concerned with circular holes
739  // microvias are laser-drilled, so we're only concerned with standard vias
740 
741  struct DRILLED_HOLE
742  {
743  wxPoint m_location;
744  int m_drillRadius;
745  BOARD_ITEM* m_owner;
746  };
747 
748  std::vector<DRILLED_HOLE> holes;
749  DRILLED_HOLE hole;
750 
751  for( MODULE* mod : m_pcb->Modules() )
752  {
753  for( D_PAD* pad : mod->Pads( ) )
754  {
755  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
756  {
757  hole.m_location = pad->GetPosition();
758  hole.m_drillRadius = pad->GetDrillSize().x / 2;
759  hole.m_owner = pad;
760  holes.push_back( hole );
761  }
762  }
763  }
764 
765  for( TRACK* track : m_pcb->Tracks() )
766  {
767  VIA* via = dynamic_cast<VIA*>( track );
768  if( via && via->GetViaType() == VIA_THROUGH )
769  {
770  hole.m_location = via->GetPosition();
771  hole.m_drillRadius = via->GetDrillValue() / 2;
772  hole.m_owner = via;
773  holes.push_back( hole );
774  }
775  }
776 
777  for( size_t ii = 0; ii < holes.size(); ++ii )
778  {
779  const DRILLED_HOLE& refHole = holes[ ii ];
780 
781  for( size_t jj = ii + 1; jj < holes.size(); ++jj )
782  {
783  const DRILLED_HOLE& checkHole = holes[ jj ];
784 
785  // Holes with identical locations are allowable
786  if( checkHole.m_location == refHole.m_location )
787  continue;
788 
789  if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
790  < checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
791  {
793  DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
794  refHole.m_owner, refHole.m_location,
795  checkHole.m_owner, checkHole.m_location ) );
796  }
797  }
798  }
799 }
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
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
#define DRCE_DRILLED_HOLES_TOO_CLOSE
overlapping drilled holes break drill bits
Definition: drc.h:99
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
int m_HoleToHoleMin
Min width of peninsula between two drilled holes.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:291
VIATYPE_T GetViaType() const
Definition: class_track.h:461
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
const wxPoint GetPosition() const override
Definition: class_track.h:433
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
#define mod(a, n)
Definition: greymap.cpp:24

References addMarkerToPcb(), DRCE_DRILLED_HOLES_TOO_CLOSE, BOARD::GetDesignSettings(), VIA::GetDrillValue(), GetLineLength(), VIA::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), VIA::GetViaType(), KiROUND(), BOARD_DESIGN_SETTINGS::m_HoleToHoleMin, m_pcb, m_pcbEditorFrame, mod, BOARD::Modules(), PAD_DRILL_SHAPE_CIRCLE, BOARD::Tracks(), and VIA_THROUGH.

Referenced by RunTests().

◆ testKeepoutAreas()

void DRC::testKeepoutAreas ( )
private

Definition at line 925 of file drc.cpp.

926 {
927  // Test keepout areas for vias, tracks and pads inside keepout areas
928  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
929  {
930  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
931 
932  if( !area->GetIsKeepout() )
933  {
934  continue;
935  }
936 
937  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
938  {
939  if( segm->Type() == PCB_TRACE_T )
940  {
941  if( !area->GetDoNotAllowTracks() )
942  continue;
943 
944  // Ignore if the keepout zone is not on the same layer
945  if( !area->IsOnLayer( segm->GetLayer() ) )
946  continue;
947 
948  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
949 
950  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
953  }
954  else if( segm->Type() == PCB_VIA_T )
955  {
956  if( ! area->GetDoNotAllowVias() )
957  continue;
958 
959  auto viaLayers = segm->GetLayerSet();
960 
961  if( !area->CommonLayerExists( viaLayers ) )
962  continue;
963 
964  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
967  }
968  }
969  // Test pads: TODO
970  }
971 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
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
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
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:234
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:85
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:227
bool GetDoNotAllowVias() const
Definition: class_zone.h:623
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:621
Definition: seg.h:36
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc.h:86
bool GetDoNotAllowTracks() const
Definition: class_zone.h:624
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230

References addMarkerToPcb(), ZONE_CONTAINER::CommonLayerExists(), SHAPE_POLY_SET::Distance(), DRCE_TRACK_INSIDE_KEEPOUT, DRCE_VIA_INSIDE_KEEPOUT, BOARD::GetArea(), BOARD::GetAreaCount(), ZONE_CONTAINER::GetDoNotAllowTracks(), ZONE_CONTAINER::GetDoNotAllowVias(), ZONE_CONTAINER::GetIsKeepout(), ZONE_CONTAINER::IsOnLayer(), m_markerFactory, m_pcb, BOARD::m_Track, DRC_MARKER_FACTORY::NewMarker(), ZONE_CONTAINER::Outline(), PCB_TRACE_T, and PCB_VIA_T.

Referenced by RunTests().

◆ testNetClasses()

bool DRC::testNetClasses ( )
private

Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings.

This is necessary because the actual DRC checks are run against the NETCLASS limits, so in order enforce global limits, we first check the NETCLASSes against the global limits.

Returns
bool - true if succes, else false but only after reporting all NETCLASS violations.

Definition at line 662 of file drc.cpp.

663 {
664  bool ret = true;
665 
667 
668  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
669 
670  if( !doNetClass( netclasses.GetDefault(), msg ) )
671  ret = false;
672 
673  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
674  {
675  NETCLASSPTR nc = i->second;
676 
677  if( !doNetClass( nc, msg ) )
678  ret = false;
679  }
680 
681  return ret;
682 }
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
Definition: drc.cpp:577
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
iterator end()
Definition: netclass.h:249
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:251
BOARD * m_pcb
Definition: drc.h:227
iterator begin()
Definition: netclass.h:248
Class NETCLASSES is a container for NETCLASS instances.
Definition: netclass.h:224
size_t i
Definition: json11.cpp:597
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:268

References NETCLASSES::begin(), doNetClass(), NETCLASSES::end(), NETCLASSES::GetDefault(), BOARD::GetDesignSettings(), i, BOARD_DESIGN_SETTINGS::m_NetClasses, and m_pcb.

Referenced by RunTests().

◆ testOutline()

void DRC::testOutline ( )
private

Test that the board outline is contiguous and composed of valid elements.

Definition at line 1211 of file drc.cpp.

1212 {
1213  wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
1214 
1215  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1216  {
1218  return;
1219  }
1220 }
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:810
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
const wxPoint GetPosition() const
Definition: eda_rect.h:113
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
#define DRCE_INVALID_OUTLINE
invalid board outline
Definition: drc.h:101
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,...
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:228
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230

References addMarkerToPcb(), DRCE_INVALID_OUTLINE, BOARD::GetBoardEdgesBoundingBox(), BOARD::GetBoardPolygonOutlines(), EDA_RECT::GetPosition(), m_board_outlines, m_markerFactory, m_pcb, and DRC_MARKER_FACTORY::NewMarker().

Referenced by RunTests().

◆ testPad2Pad()

void DRC::testPad2Pad ( )
private

Definition at line 685 of file drc.cpp.

686 {
687  std::vector<D_PAD*> sortedPads;
688 
689  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
690 
691  if( sortedPads.size() == 0 )
692  return;
693 
694  // find the max size of the pads (used to stop the test)
695  int max_size = 0;
696 
697  for( unsigned i = 0; i < sortedPads.size(); ++i )
698  {
699  D_PAD* pad = sortedPads[i];
700 
701  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
702  int radius = pad->GetBoundingRadius();
703 
704  if( radius > max_size )
705  max_size = radius;
706  }
707 
708  // Upper limit of pad list (limit not included)
709  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
710 
711  // Test the pads
712  for( unsigned i = 0; i< sortedPads.size(); ++i )
713  {
714  D_PAD* pad = sortedPads[i];
715 
716  int x_limit = max_size + pad->GetClearance() +
717  pad->GetBoundingRadius() + pad->GetPosition().x;
718 
719  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
720  {
721  wxASSERT( m_currentMarker );
723  m_currentMarker = nullptr;
724  }
725  }
726 }
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:619
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:1309
MARKER_PCB * m_currentMarker
Definition: drc.h:193
size_t i
Definition: json11.cpp:597
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596
const wxPoint GetPosition() const override
Definition: class_pad.h:220

References addMarkerToPcb(), doPadToPadsDrc(), D_PAD::GetBoundingRadius(), D_PAD::GetClearance(), D_PAD::GetPosition(), BOARD::GetSortedPadListByXthenYCoord(), i, m_currentMarker, and m_pcb.

Referenced by RunTests().

◆ testTracks()

void DRC::testTracks ( wxWindow *  aActiveWindow,
bool  aShowProgressBar 
)
private

Perform the DRC on all tracks.

This test can take a while, a progress bar can be displayed

Parameters
aActiveWindow= the active window ued as parent for the progress bar
aShowProgressBar= true to show a progress bar (Note: it is shown only if there are many tracks)

Definition at line 802 of file drc.cpp.

803 {
804  wxProgressDialog * progressDialog = NULL;
805  const int delta = 500; // This is the number of tests between 2 calls to the
806  // progress bar
807  int count = 0;
808 
809  for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
810  count++;
811 
812  int deltamax = count/delta;
813 
814  if( aShowProgressBar && deltamax > 3 )
815  {
816  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
817  // on OSX
818  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
819  deltamax, aActiveWindow,
820  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
821  progressDialog->Update( 0, wxEmptyString );
822  }
823 
824  int ii = 0;
825  count = 0;
826 
827  for( TRACK* segm = m_pcb->m_Track; segm; segm = segm->Next() )
828  {
829  if( ii++ > delta )
830  {
831  ii = 0;
832  count++;
833 
834  if( progressDialog )
835  {
836  if( !progressDialog->Update( count, wxEmptyString ) )
837  break; // Aborted by user
838 #ifdef __WXMAC__
839  // Work around a dialog z-order issue on OS X
840  if( count == deltamax )
841  aActiveWindow->Raise();
842 #endif
843  }
844  }
845 
846  if( !doTrackDrc( segm, segm->Next(), true ) )
847  {
848  if( m_currentMarker )
849  {
851  m_currentMarker = nullptr;
852  }
853  }
854  }
855 
856  if( progressDialog )
857  progressDialog->Destroy();
858 }
static const int delta[8][2]
Definition: solve.cpp:112
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
MARKER_PCB * m_currentMarker
Definition: drc.h:193
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
DLIST< TRACK > m_Track
Definition: class_board.h:250

References addMarkerToPcb(), delta, doTrackDrc(), m_currentMarker, m_pcb, and BOARD::m_Track.

Referenced by RunTests().

◆ testUnconnected()

void DRC::testUnconnected ( )
private

Definition at line 861 of file drc.cpp.

862 {
863 
864  auto connectivity = m_pcb->GetConnectivity();
865 
866  connectivity->Clear();
867  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
868  connectivity->RecalculateRatsnest();
869 
870  std::vector<CN_EDGE> edges;
871  connectivity->GetUnconnectedEdges( edges );
872 
873  for( const auto& edge : edges )
874  {
875  auto src = edge.GetSourcePos();
876  auto dst = edge.GetTargetPos();
877 
878  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
880  edge.GetSourceNode()->Parent(),
881  wxPoint( src.x, src.y ),
882  edge.GetTargetNode()->Parent(),
883  wxPoint( dst.x, dst.y ) ) );
884 
885  }
886 }
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc.h:49
BOARD * m_pcb
Definition: drc.h:227
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:291
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:232

References DRCE_UNCONNECTED_ITEMS, BOARD::GetConnectivity(), EDA_DRAW_FRAME::GetUserUnits(), m_pcb, m_pcbEditorFrame, and m_unconnected.

Referenced by ListUnconnectedPads(), and RunTests().

◆ testZones()

void DRC::testZones ( )
private

Definition at line 889 of file drc.cpp.

890 {
891  // Test copper areas for valid netcodes
892  // if a netcode is < 0 the netname was not found when reading a netlist
893  // if a netcode is == 0 the netname is void, and the zone is not connected.
894  // This is allowed, but i am not sure this is a good idea
895  //
896  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
897  // is stored, and initialized from the file or the zone properties editor.
898  // if it differs from the net name from net code, there is a DRC issue
899  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
900  {
901  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
902 
903  if( !zone->IsOnCopperLayer() )
904  continue;
905 
906  int netcode = zone->GetNetCode();
907  // a netcode < 0 or > 0 and no pad in net is a error or strange
908  // perhaps a "dead" net, which happens when all pads in this net were removed
909  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
910  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
911 
912  if( ( netcode < 0 ) || pads_in_net == 0 )
913  {
914  wxPoint markerPos = zone->GetPosition();
916  markerPos, zone, DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE ) );
917  }
918  }
919 
920  // Test copper areas outlines, and create markers when needed
921  TestZoneToZoneOutline( NULL, true );
922 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
int GetNetCode() const
Function GetNetCode.
int TestZoneToZoneOutline(ZONE_CONTAINER *aZone, bool aCreateMarkers)
Tests whether distance between zones complies with the DRC rules.
Definition: drc.cpp:217
const wxPoint GetPosition() const override
Definition: class_zone.cpp:169
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:71
BOARD * m_pcb
Definition: drc.h:227
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:102
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181

References addMarkerToPcb(), DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE, BOARD::GetArea(), BOARD::GetAreaCount(), BOARD::GetConnectivity(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPosition(), ZONE_CONTAINER::IsOnCopperLayer(), m_markerFactory, m_pcb, DRC_MARKER_FACTORY::NewMarker(), and TestZoneToZoneOutline().

Referenced by RunTests().

◆ TestZoneToZoneOutline()

int DRC::TestZoneToZoneOutline ( ZONE_CONTAINER aZone,
bool  aCreateMarkers 
)

Tests whether distance between zones complies with the DRC rules.

Parameters
aZonezone to compare with other zones, or if NULL then all zones are compared to all others.
aCreateMarkersif true create DRC markers. False: do not create markers. only fing drc errors
Returns
Errors count

Definition at line 217 of file drc.cpp.

218 {
219  BOARD* board = m_pcbEditorFrame->GetBoard();
220  BOARD_COMMIT commit( m_pcbEditorFrame );
221  int nerrors = 0;
222 
223  std::vector<SHAPE_POLY_SET> smoothed_polys;
224  smoothed_polys.resize( board->GetAreaCount() );
225 
226  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
227  {
228  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
229  zoneRef->BuildSmoothedPoly( smoothed_polys[ia] );
230  }
231 
232  // iterate through all areas
233  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
234  {
235  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
236 
237  if( !zoneRef->IsOnCopperLayer() )
238  continue;
239 
240  // When testing only a single area, skip all others
241  if( aZone && ( aZone != zoneRef) )
242  continue;
243 
244  // If we are testing a single zone, then iterate through all other zones
245  // Otherwise, we have already tested the zone combination
246  for( int ia2 = ( aZone ? 0 : ia + 1 ); ia2 < board->GetAreaCount(); ia2++ )
247  {
248  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
249 
250  if( zoneRef == zoneToTest )
251  continue;
252 
253  // test for same layer
254  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
255  continue;
256 
257  // Test for same net
258  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
259  continue;
260 
261  // test for different priorities
262  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
263  continue;
264 
265  // test for different types
266  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
267  continue;
268 
269  // Examine a candidate zone: compare zoneToTest to zoneRef
270 
271  // Get clearance used in zone to zone test. The policy used to
272  // obtain that value is now part of the zone object itself by way of
273  // ZONE_CONTAINER::GetClearance().
274  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
275 
276  // Keepout areas have no clearance, so set zone2zoneClearance to 1
277  // ( zone2zoneClearance = 0 can create problems in test functions)
278  if( zoneRef->GetIsKeepout() )
279  zone2zoneClearance = 1;
280 
281  // test for some corners of zoneRef inside zoneToTest
282  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
283  {
284  VECTOR2I currentVertex = *iterator;
285  wxPoint pt( currentVertex.x, currentVertex.y );
286 
287  if( smoothed_polys[ia2].Contains( currentVertex ) )
288  {
289  if( aCreateMarkers )
290  commit.Add( m_markerFactory.NewMarker(
291  pt, zoneRef, zoneToTest, DRCE_ZONES_INTERSECT ) );
292 
293  nerrors++;
294  }
295  }
296 
297  // test for some corners of zoneToTest inside zoneRef
298  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
299  {
300  VECTOR2I currentVertex = *iterator;
301  wxPoint pt( currentVertex.x, currentVertex.y );
302 
303  if( smoothed_polys[ia].Contains( currentVertex ) )
304  {
305  if( aCreateMarkers )
306  commit.Add( m_markerFactory.NewMarker(
307  pt, zoneToTest, zoneRef, DRCE_ZONES_INTERSECT ) );
308 
309  nerrors++;
310  }
311  }
312 
313  // Iterate through all the segments of refSmoothedPoly
314  std::set<wxPoint> conflictPoints;
315 
316  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
317  {
318  // Build ref segment
319  SEG refSegment = *refIt;
320 
321  // Iterate through all the segments in smoothed_polys[ia2]
322  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
323  {
324  // Build test segment
325  SEG testSegment = *testIt;
326  wxPoint pt;
327 
328  int ax1, ay1, ax2, ay2;
329  ax1 = refSegment.A.x;
330  ay1 = refSegment.A.y;
331  ax2 = refSegment.B.x;
332  ay2 = refSegment.B.y;
333 
334  int bx1, by1, bx2, by2;
335  bx1 = testSegment.A.x;
336  by1 = testSegment.A.y;
337  bx2 = testSegment.B.x;
338  by2 = testSegment.B.y;
339 
340  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
341  0,
342  ax1, ay1, ax2, ay2,
343  0,
344  zone2zoneClearance,
345  &pt.x, &pt.y );
346 
347  if( d < zone2zoneClearance )
348  conflictPoints.insert( pt );
349  }
350  }
351 
352  for( wxPoint pt : conflictPoints )
353  {
354  if( aCreateMarkers )
355  commit.Add( m_markerFactory.NewMarker(
356  pt, zoneRef, zoneToTest, DRCE_ZONES_TOO_CLOSE ) );
357 
358  nerrors++;
359  }
360  }
361  }
362 
363  if( aCreateMarkers )
364  commit.Push( wxEmptyString, false, false );
365 
366  return nerrors;
367 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
int GetNetCode() const
Function GetNetCode.
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
#define DRCE_ZONES_INTERSECT
copper area outlines intersect
Definition: drc.h:69
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:774
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
MARKER_PCB * NewMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode) const
Creates a marker on a track, via or pad.
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)
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:621
Definition: seg.h:36
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly if it exists,...
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:97
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
VECTOR2I A
Definition: seg.h:44
#define DRCE_ZONES_TOO_CLOSE
copper area outlines are too close
Definition: drc.h:70
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
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:230
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
VECTOR2I B
Definition: seg.h:45

References SEG::A, COMMIT::Add(), SEG::B, ZONE_CONTAINER::BuildSmoothedPoly(), DRCE_ZONES_INTERSECT, DRCE_ZONES_TOO_CLOSE, BOARD::GetArea(), BOARD::GetAreaCount(), PCB_BASE_FRAME::GetBoard(), ZONE_CONTAINER::GetClearance(), GetClearanceBetweenSegments(), ZONE_CONTAINER::GetIsKeepout(), ZONE_CONTAINER::GetLayer(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPriority(), ZONE_CONTAINER::IsOnCopperLayer(), m_markerFactory, m_pcbEditorFrame, DRC_MARKER_FACTORY::NewMarker(), BOARD_COMMIT::Push(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PCB_EDIT_FRAME::duplicateZone(), PCB_EDIT_FRAME::End_Move_Zone_Corner_Or_Outlines(), PCB_EDIT_FRAME::End_Zone(), PCB_EDIT_FRAME::Remove_Zone_Corner(), and testZones().

◆ updatePointers()

void DRC::updatePointers ( )
private

Update needed pointers from the one pointer which is known not to change.

Definition at line 560 of file drc.cpp.

561 {
562  // update my pointers, m_pcbEditorFrame is the only unchangeable one
564 
565  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
566  {
571 
573  }
574 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:229
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:663
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc.h:227
void SetList(EDA_UNITS_T aUnits, DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
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
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:226
Class DRC_LIST_UNCONNECTED is an implementation of the interface named DRC_ITEM_LIST which uses a vec...
BOARD * GetBoard() const
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:232

References PCB_BASE_FRAME::GetBoard(), EDA_DRAW_FRAME::GetUserUnits(), DIALOG_DRC_CONTROL_BASE::m_ClearanceListBox, m_drcDialog, m_pcb, m_pcbEditorFrame, m_unconnected, DIALOG_DRC_CONTROL_BASE::m_UnconnectedListBox, DRCLISTBOX::SetList(), and DIALOG_DRC_CONTROL::UpdateDisplayedCounts().

Referenced by DrcOnCreatingTrack(), DrcOnCreatingZone(), ListUnconnectedPads(), RunTests(), and ShowDRCDialog().

Friends And Related Function Documentation

◆ DIALOG_DRC_CONTROL

friend class DIALOG_DRC_CONTROL
friend

Definition at line 178 of file drc.h.

Referenced by ShowDRCDialog().

Member Data Documentation

◆ m_board_outlines

SHAPE_POLY_SET DRC::m_board_outlines
private

The board outline including cutouts.

Definition at line 228 of file drc.h.

Referenced by doTrackDrc(), and testOutline().

◆ m_currentMarker

◆ m_doCreateRptFile

bool DRC::m_doCreateRptFile
private

Definition at line 187 of file drc.h.

Referenced by DestroyDRCDialog(), DRC(), SetSettings(), and ShowDRCDialog().

◆ m_doKeepoutTest

bool DRC::m_doKeepoutTest
private

Definition at line 186 of file drc.h.

Referenced by DRC(), RunTests(), and SetSettings().

◆ m_doPad2PadTest

bool DRC::m_doPad2PadTest
private

Definition at line 183 of file drc.h.

Referenced by DRC(), RunTests(), and SetSettings().

◆ m_doUnconnectedTest

bool DRC::m_doUnconnectedTest
private

Definition at line 184 of file drc.h.

Referenced by DRC(), RunTests(), and SetSettings().

◆ m_doZonesTest

bool DRC::m_doZonesTest
private

Definition at line 185 of file drc.h.

Referenced by DRC(), and SetSettings().

◆ m_drcDialog

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 229 of file drc.h.

Referenced by DestroyDRCDialog(), DRC(), ShowDRCDialog(), and updatePointers().

◆ m_drcInLegacyRoutingMode

bool DRC::m_drcInLegacyRoutingMode
private

in legacy canvas, when creating a track, the drc test must only display the error message, and do not create a DRC marker.

if m_drcInLegacyRoutingMode it true only the message will be displayed m_drcInLegacyRoutingMode = false is the normal Drc mode

Definition at line 201 of file drc.h.

Referenced by addMarkerToPcb(), doTrackDrc(), DRC(), DrcOnCreatingTrack(), DrcOnCreatingZone(), and SetSettings().

◆ m_markerFactory

◆ m_padToTestPos

wxPoint DRC::m_padToTestPos
private

Definition at line 207 of file drc.h.

Referenced by checkClearancePadToPad(), checkClearanceSegmToPad(), and doTrackDrc().

◆ m_pcb

◆ m_pcbEditorFrame

PCB_EDIT_FRAME* DRC::m_pcbEditorFrame
private

◆ m_refillZones

bool DRC::m_refillZones
private

Definition at line 188 of file drc.h.

Referenced by DRC(), RunTests(), and SetSettings().

◆ m_reportAllTrackErrors

bool DRC::m_reportAllTrackErrors
private

Definition at line 189 of file drc.h.

Referenced by doTrackDrc(), DRC(), DrcOnCreatingTrack(), DrcOnCreatingZone(), and SetSettings().

◆ m_rptFilename

wxString DRC::m_rptFilename
private

Definition at line 191 of file drc.h.

Referenced by DestroyDRCDialog(), SetSettings(), and ShowDRCDialog().

◆ m_segmAngle

double DRC::m_segmAngle
private

Definition at line 215 of file drc.h.

Referenced by checkClearancePadToPad(), checkClearanceSegmToPad(), doTrackDrc(), and DRC().

◆ m_segmEnd

wxPoint DRC::m_segmEnd
private

Definition at line 208 of file drc.h.

Referenced by checkClearancePadToPad(), checkClearanceSegmToPad(), and doTrackDrc().

◆ m_segmLength

int DRC::m_segmLength
private

Definition at line 216 of file drc.h.

Referenced by checkClearancePadToPad(), checkClearanceSegmToPad(), doTrackDrc(), and DRC().

◆ m_unconnected

DRC_LIST DRC::m_unconnected
private

list of unconnected pads, as DRC_ITEMs

Definition at line 232 of file drc.h.

Referenced by testUnconnected(), updatePointers(), and ~DRC().

◆ m_xcliphi

int DRC::m_xcliphi
private

Definition at line 223 of file drc.h.

Referenced by checkClearanceSegmToPad(), checkLine(), doTrackDrc(), and DRC().

◆ m_xcliplo

int DRC::m_xcliplo
private

Definition at line 221 of file drc.h.

Referenced by checkClearanceSegmToPad(), checkLine(), doTrackDrc(), and DRC().

◆ m_ycliphi

int DRC::m_ycliphi
private

Definition at line 224 of file drc.h.

Referenced by checkClearanceSegmToPad(), checkLine(), doTrackDrc(), and DRC().

◆ m_ycliplo

int DRC::m_ycliplo
private

Definition at line 222 of file drc.h.

Referenced by checkClearanceSegmToPad(), checkLine(), doTrackDrc(), and DRC().


The documentation for this class was generated from the following files: