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 RunTests (wxTextCtrl *aMessages=NULL)
 Run all the tests specified with a previous call to SetSettings() More...
 
MARKER_PCBGetCurrentMarker ()
 

Static Public Member Functions

static void TestFootprints (NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS_T aUnits, DRC_LIST &aDRCList)
 Test the board footprints against a netlist. More...
 

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 aTestPads, bool aTestZones)
 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
 
bool m_testFootprints
 
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...
 
DRC_LIST m_footprints
 list of footprint warnings, as DRC_ITEMs More...
 
bool m_drcRun
 
bool m_footprintsTested
 

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 188 of file drc.h.

Constructor & Destructor Documentation

◆ DRC()

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 135 of file drc.cpp.

136 {
137  m_pcbEditorFrame = aPcbWindow;
138  m_pcb = aPcbWindow->GetBoard();
139  m_drcDialog = NULL;
140 
141  // establish initial values for everything:
142  m_drcInLegacyRoutingMode = false;
143  m_doPad2PadTest = true; // enable pad to pad clearance tests
144  m_doUnconnectedTest = true; // enable unconnected tests
145  m_doZonesTest = false; // disable zone to items clearance tests
146  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
147  m_refillZones = false; // Only fill zones if requested by user.
148  m_reportAllTrackErrors = false;
149  m_testFootprints = false;
150 
151  m_drcRun = false;
152  m_footprintsTested = false;
153 
154  m_doCreateRptFile = false;
155  // m_rptFilename set to empty by its constructor
156 
157  m_currentMarker = NULL;
158 
159  m_segmAngle = 0;
160  m_segmLength = 0;
161 
162  m_xcliplo = 0;
163  m_ycliplo = 0;
164  m_xcliphi = 0;
165  m_ycliphi = 0;
166 
167  m_markerFactory.SetUnitsProvider( [=]() { return aPcbWindow->GetUserUnits(); } );
168 }
bool m_refillZones
Definition: drc.h:200
bool m_doCreateRptFile
Definition: drc.h:199
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
int m_ycliplo
Definition: drc.h:235
int m_ycliphi
Definition: drc.h:237
int m_segmLength
Definition: drc.h:229
BOARD * m_pcb
Definition: drc.h:240
bool m_testFootprints
Definition: drc.h:202
bool m_doKeepoutTest
Definition: drc.h:198
bool m_doZonesTest
Definition: drc.h:197
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:289
bool m_reportAllTrackErrors
Definition: drc.h:201
bool m_drcRun
Definition: drc.h:247
int m_xcliphi
Definition: drc.h:236
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
bool m_doPad2PadTest
Definition: drc.h:195
bool m_footprintsTested
Definition: drc.h:248
MARKER_PCB * m_currentMarker
Definition: drc.h:206
BOARD * GetBoard() const
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
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:214
int m_xcliplo
Definition: drc.h:234
bool m_doUnconnectedTest
Definition: drc.h:196
double m_segmAngle
Definition: drc.h:228

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_drcRun, m_footprintsTested, m_markerFactory, m_pcb, m_pcbEditorFrame, m_refillZones, m_reportAllTrackErrors, m_segmAngle, m_segmLength, m_testFootprints, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, and DRC_MARKER_FACTORY::SetUnitsProvider().

◆ ~DRC()

DRC::~DRC ( )

Definition at line 171 of file drc.cpp.

172 {
173  for( DRC_ITEM* unconnectedItem : m_unconnected )
174  delete unconnectedItem;
175 
176  for( DRC_ITEM* footprintItem : m_footprints )
177  delete footprintItem;
178 }
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
DRC_LIST m_footprints
list of footprint warnings, as DRC_ITEMs
Definition: drc.h:246
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:245

References m_footprints, 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 104 of file drc.cpp.

105 {
106  // In legacy routing mode, do not add markers to the board.
107  // only shows the drc error message
109  {
110  m_pcbEditorFrame->SetMsgPanel( aMarker );
111  delete aMarker;
112  m_currentMarker = nullptr;
113  }
114  else
115  {
116  BOARD_COMMIT commit( m_pcbEditorFrame );
117  commit.Add( aMarker );
118  commit.Push( wxEmptyString, false, false );
119  }
120 }
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:239
MARKER_PCB * m_currentMarker
Definition: drc.h:206
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:214

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 869 of file drc_clearance_test_functions.cpp.

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

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 1150 of file drc_clearance_test_functions.cpp.

1151 {
1152  // Note:
1153  // we are using a horizontal segment for test, because we know here
1154  // only the length and orientation+ of the segment
1155  // Therefore the coordinates of the shape of pad to compare
1156  // must be calculated in a axis system rotated by m_segmAngle
1157  // and centered to the segment origin, before they can be tested
1158  // against the segment
1159  // We are using:
1160  // m_padToTestPos the position of the pad shape in this axis system
1161  // m_segmAngle the axis system rotation
1162 
1163  int segmHalfWidth = aSegmentWidth / 2;
1164  int distToLine = segmHalfWidth + aMinDist;
1165 
1166  wxSize padHalfsize; // half dimension of the pad
1167 
1168  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1169  {
1170  // For a custom pad, the pad size has no meaning, we only can
1171  // use the bounding radius
1172  padHalfsize.x = padHalfsize.y = aPad->GetBoundingRadius();
1173  }
1174  else
1175  {
1176  padHalfsize = aPad->GetSize() / 2;
1177  }
1178 
1179  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
1180  {
1181  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
1182  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
1183  }
1184 
1185  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1186  {
1187  /* Easy case: just test the distance between segment and pad centre
1188  * calculate pad coordinates in the X,Y axis with X axis = segment to test
1189  */
1191  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
1192  }
1193 
1194  /* calculate the bounding box of the pad, including the clearance and the segment width
1195  * if the line from 0 to m_segmEnd does not intersect this bounding box,
1196  * the clearance is always OK
1197  * But if intersect, a better analysis of the pad shape must be done.
1198  */
1199  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
1200  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
1201  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
1202  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
1203 
1204  wxPoint startPoint( 0, 0 );
1205  wxPoint endPoint = m_segmEnd;
1206 
1207  double orient = aPad->GetOrientation();
1208 
1209  RotatePoint( &startPoint, m_padToTestPos, -orient );
1210  RotatePoint( &endPoint, m_padToTestPos, -orient );
1211 
1212  if( checkLine( startPoint, endPoint ) )
1213  return true;
1214 
1215  /* segment intersects the bounding box. But there is not always a DRC error.
1216  * A fine analysis of the pad shape must be done.
1217  */
1218  switch( aPad->GetShape() )
1219  {
1220  case PAD_SHAPE_CIRCLE:
1221  // This case was already tested, so it cannot be found here.
1222  // it is here just to avoid compil warning, and to remember
1223  // it is already tested.
1224  return false;
1225 
1226  case PAD_SHAPE_OVAL:
1227  {
1228  /* an oval is a complex shape, but is a rectangle and 2 circles
1229  * these 3 basic shapes are more easy to test.
1230  *
1231  * In calculations we are using a vertical or horizontal oval shape
1232  * (i.e. a vertical or horizontal rounded segment)
1233  */
1234  wxPoint cstart = m_padToTestPos;
1235  wxPoint cend = m_padToTestPos; // center of each circle
1236  int delta = std::abs( padHalfsize.y - padHalfsize.x );
1237  int radius = std::min( padHalfsize.y, padHalfsize.x );
1238 
1239  if( padHalfsize.x > padHalfsize.y ) // horizontal equivalent segment
1240  {
1241  cstart.x -= delta;
1242  cend.x += delta;
1243  // Build the rectangular clearance area between the two circles
1244  // the rect starts at cstart.x and ends at cend.x and its height
1245  // is (radius + distToLine)*2
1246  m_xcliplo = cstart.x;
1247  m_ycliplo = cstart.y - radius - distToLine;
1248  m_xcliphi = cend.x;
1249  m_ycliphi = cend.y + radius + distToLine;
1250  }
1251  else // vertical equivalent segment
1252  {
1253  cstart.y -= delta;
1254  cend.y += delta;
1255  // Build the rectangular clearance area between the two circles
1256  // the rect starts at cstart.y and ends at cend.y and its width
1257  // is (radius + distToLine)*2
1258  m_xcliplo = cstart.x - distToLine - radius;
1259  m_ycliplo = cstart.y;
1260  m_xcliphi = cend.x + distToLine + radius;
1261  m_ycliphi = cend.y;
1262  }
1263 
1264  // Test the rectangular clearance area between the two circles (the rounded ends)
1265  // If the segment legth is zero, only check the endpoints, skip the rectangle
1266  if( m_segmLength && !checkLine( startPoint, endPoint ) )
1267  {
1268  return false;
1269  }
1270 
1271  // test the first end
1272  // Calculate the actual position of the circle, given the pad orientation:
1273  RotatePoint( &cstart, m_padToTestPos, orient );
1274 
1275  // Calculate the actual position of the circle in the new X,Y axis, relative
1276  // to the segment:
1277  RotatePoint( &cstart, m_segmAngle );
1278 
1279  if( !checkMarginToCircle( cstart, radius + distToLine, m_segmLength ) )
1280  {
1281  return false;
1282  }
1283 
1284  // test the second end
1285  RotatePoint( &cend, m_padToTestPos, orient );
1286  RotatePoint( &cend, m_segmAngle );
1287 
1288  if( !checkMarginToCircle( cend, radius + distToLine, m_segmLength ) )
1289  {
1290  return false;
1291  }
1292  }
1293  break;
1294 
1295  case PAD_SHAPE_ROUNDRECT:
1296  {
1297  // a round rect is a smaller rect, with a clearance augmented by the corners radius
1298  int r = aPad->GetRoundRectCornerRadius();
1299  padHalfsize.x -= r;
1300  padHalfsize.y -= r;
1301  distToLine += r;
1302  }
1303  // Fall through
1304  case PAD_SHAPE_RECT:
1305  // the area to test is a rounded rectangle.
1306  // this can be done by testing 2 rectangles and 4 circles (the corners)
1307 
1308  // Testing the first rectangle dimx + distToLine, dimy:
1309  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
1310  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
1311  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
1312  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
1313 
1314  if( !checkLine( startPoint, endPoint ) )
1315  return false;
1316 
1317  // Testing the second rectangle dimx , dimy + distToLine
1318  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
1319  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
1320  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
1321  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
1322 
1323  if( !checkLine( startPoint, endPoint ) )
1324  return false;
1325 
1326  // testing the 4 circles which are the clearance area of each corner:
1327 
1328  // testing the left top corner of the rectangle
1329  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1330  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1331  RotatePoint( &startPoint, m_padToTestPos, orient );
1332  RotatePoint( &startPoint, m_segmAngle );
1333 
1334  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1335  return false;
1336 
1337  // testing the right top corner of the rectangle
1338  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1339  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1340  RotatePoint( &startPoint, m_padToTestPos, orient );
1341  RotatePoint( &startPoint, m_segmAngle );
1342 
1343  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1344  return false;
1345 
1346  // testing the left bottom corner of the rectangle
1347  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1348  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1349  RotatePoint( &startPoint, m_padToTestPos, orient );
1350  RotatePoint( &startPoint, m_segmAngle );
1351 
1352  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1353  return false;
1354 
1355  // testing the right bottom corner of the rectangle
1356  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1357  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1358  RotatePoint( &startPoint, m_padToTestPos, orient );
1359  RotatePoint( &startPoint, m_segmAngle );
1360 
1361  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1362  return false;
1363 
1364  break;
1365 
1366  case PAD_SHAPE_TRAPEZOID:
1367  {
1368  wxPoint poly[4];
1369  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
1370 
1371  // Move shape to m_padToTestPos
1372  for( int ii = 0; ii < 4; ii++ )
1373  {
1374  poly[ii] += m_padToTestPos;
1375  RotatePoint( &poly[ii], m_segmAngle );
1376  }
1377 
1378  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ),
1379  wxPoint(m_segmLength,0), distToLine ) )
1380  return false;
1381  }
1382  break;
1383 
1384  case PAD_SHAPE_CUSTOM:
1385  {
1386  SHAPE_POLY_SET polyset;
1387  polyset.Append( aPad->GetCustomShapeAsPolygon() );
1388  // The pad can be rotated. calculate the coordinates
1389  // relatives to the segment being tested
1390  // Note, the pad position relative to the segment origin
1391  // is m_padToTestPos
1392  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1393  m_padToTestPos, orient );
1394 
1395  // Rotate all coordinates by m_segmAngle, because the segment orient
1396  // is m_segmAngle
1397  // we are using a horizontal segment for test, because we know here
1398  // only the lenght and orientation+ of the segment
1399  // therefore all coordinates of the pad to test must be rotated by
1400  // m_segmAngle (they are already relative to the segment origin)
1401  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1402  wxPoint( 0, 0 ), m_segmAngle );
1403 
1404  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1405 
1406  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1407  refpoly.PointCount(),
1408  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1409  distToLine ) )
1410  return false;
1411  }
1412  break;
1413 
1415  {
1416  SHAPE_POLY_SET polyset;
1417  // The pad can be rotated. calculate the coordinates
1418  // relatives to the segment being tested
1419  // Note, the pad position relative to the segment origin
1420  // is m_padToTestPos
1421  int padRadius = aPad->GetRoundRectCornerRadius();
1423  aPad->GetOrientation(),
1424  padRadius, aPad->GetChamferRectRatio(),
1425  aPad->GetChamferPositions(), 64 );
1426  // Rotate also coordinates by m_segmAngle, because the segment orient
1427  // is m_segmAngle.
1428  // we are using a horizontal segment for test, because we know here
1429  // only the lenght and orientation of the segment
1430  // therefore all coordinates of the pad to test must be rotated by
1431  // m_segmAngle (they are already relative to the segment origin)
1432  polyset.Rotate( DECIDEG2RAD( -m_segmAngle ), VECTOR2I( 0, 0 ) );
1433 
1434  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1435 
1436  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1437  refpoly.PointCount(),
1438  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1439  distToLine ) )
1440  return false;
1441  }
1442  break;
1443  }
1444 
1445  return true;
1446 }
int m_ycliplo
Definition: drc.h:235
int m_ycliphi
Definition: drc.h:237
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc.h:229
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aCircleToSegmentsCount)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
int PointCount() const
Function PointCount()
wxPoint m_padToTestPos
Definition: drc.h:220
#define abs(a)
Definition: auxiliary.h:84
static const int delta[8][2]
Definition: solve.cpp:112
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:695
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.
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:672
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:624
const wxSize & GetDelta() const
Definition: class_pad.h:274
int m_xcliphi
Definition: drc.h:236
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:221
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:394
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:346
double DECIDEG2RAD(double deg)
Definition: trigo.h:212
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:543
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:218
const wxSize & GetSize() const
Definition: class_pad.h:271
void Rotate(double aAngle, const VECTOR2I &aCenter)
Function Rotate rotates all vertices by a given angle.
int m_xcliplo
Definition: drc.h:234
double m_segmAngle
Definition: drc.h:228
#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(), DECIDEG2RAD(), delta, D_PAD::GetBoundingRadius(), D_PAD::GetChamferPositions(), D_PAD::GetChamferRectRatio(), 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_CHAMFERED_RECT, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), poly2segmentDRC(), SHAPE_POLY_SET::Rotate(), RotatePoint(), and TransformRoundChamferedRectToPolygon().

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 1508 of file drc_clearance_test_functions.cpp.

1509 {
1510 #define WHEN_OUTSIDE return true
1511 #define WHEN_INSIDE
1512  int temp;
1513 
1514  if( aSegStart.x > aSegEnd.x )
1515  std::swap( aSegStart, aSegEnd );
1516 
1517  if( (aSegEnd.x <= m_xcliplo) || (aSegStart.x >= m_xcliphi) )
1518  {
1519  WHEN_OUTSIDE;
1520  }
1521 
1522  if( aSegStart.y < aSegEnd.y )
1523  {
1524  if( (aSegEnd.y <= m_ycliplo) || (aSegStart.y >= m_ycliphi) )
1525  {
1526  WHEN_OUTSIDE;
1527  }
1528 
1529  if( aSegStart.y < m_ycliplo )
1530  {
1531  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1532  (aSegEnd.y - aSegStart.y) );
1533 
1534  if( (aSegStart.x += temp) >= m_xcliphi )
1535  {
1536  WHEN_OUTSIDE;
1537  }
1538 
1539  aSegStart.y = m_ycliplo;
1540  WHEN_INSIDE;
1541  }
1542 
1543  if( aSegEnd.y > m_ycliphi )
1544  {
1545  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1546  (aSegEnd.y - aSegStart.y) );
1547 
1548  if( (aSegEnd.x -= temp) <= m_xcliplo )
1549  {
1550  WHEN_OUTSIDE;
1551  }
1552 
1553  aSegEnd.y = m_ycliphi;
1554  WHEN_INSIDE;
1555  }
1556 
1557  if( aSegStart.x < m_xcliplo )
1558  {
1559  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1560  (aSegEnd.x - aSegStart.x) );
1561  aSegStart.y += temp;
1562  aSegStart.x = m_xcliplo;
1563  WHEN_INSIDE;
1564  }
1565 
1566  if( aSegEnd.x > m_xcliphi )
1567  {
1568  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1569  (aSegEnd.x - aSegStart.x) );
1570  aSegEnd.y -= temp;
1571  aSegEnd.x = m_xcliphi;
1572  WHEN_INSIDE;
1573  }
1574  }
1575  else
1576  {
1577  if( (aSegStart.y <= m_ycliplo) || (aSegEnd.y >= m_ycliphi) )
1578  {
1579  WHEN_OUTSIDE;
1580  }
1581 
1582  if( aSegStart.y > m_ycliphi )
1583  {
1584  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1585  (aSegStart.y - aSegEnd.y) );
1586 
1587  if( (aSegStart.x += temp) >= m_xcliphi )
1588  {
1589  WHEN_OUTSIDE;
1590  }
1591 
1592  aSegStart.y = m_ycliphi;
1593  WHEN_INSIDE;
1594  }
1595 
1596  if( aSegEnd.y < m_ycliplo )
1597  {
1598  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1599  (aSegStart.y - aSegEnd.y) );
1600 
1601  if( (aSegEnd.x -= temp) <= m_xcliplo )
1602  {
1603  WHEN_OUTSIDE;
1604  }
1605 
1606  aSegEnd.y = m_ycliplo;
1607  WHEN_INSIDE;
1608  }
1609 
1610  if( aSegStart.x < m_xcliplo )
1611  {
1612  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1613  (aSegEnd.x - aSegStart.x) );
1614  aSegStart.y -= temp;
1615  aSegStart.x = m_xcliplo;
1616  WHEN_INSIDE;
1617  }
1618 
1619  if( aSegEnd.x > m_xcliphi )
1620  {
1621  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1622  (aSegEnd.x - aSegStart.x) );
1623  aSegEnd.y += temp;
1624  aSegEnd.x = m_xcliphi;
1625  WHEN_INSIDE;
1626  }
1627  }
1628 
1629  // Do not divide here to avoid rounding errors
1630  if( ( (aSegEnd.x + aSegStart.x) < m_xcliphi * 2 )
1631  && ( (aSegEnd.x + aSegStart.x) > m_xcliplo * 2) \
1632  && ( (aSegEnd.y + aSegStart.y) < m_ycliphi * 2 )
1633  && ( (aSegEnd.y + aSegStart.y) > m_ycliplo * 2 ) )
1634  {
1635  return false;
1636  }
1637  else
1638  {
1639  return true;
1640  }
1641 }
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
int m_ycliplo
Definition: drc.h:235
int m_ycliphi
Definition: drc.h:237
int m_xcliphi
Definition: drc.h:236
#define WHEN_INSIDE
int m_xcliplo
Definition: drc.h:234

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 1455 of file drc_clearance_test_functions.cpp.

1456 {
1457  if( abs( aCentre.y ) >= aRadius ) // trivial case
1458  return true;
1459 
1460  // Here, distance between aCentre and X axis is < aRadius
1461  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1462  {
1463  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1464  return false; // aCentre is between the starting point and the ending point of the segm
1465 
1466  if( aCentre.x > aLength ) // aCentre is after the ending point
1467  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1468 
1469  if( EuclideanNorm( aCentre ) < aRadius )
1470  // distance between aCentre and the starting point or the ending point is < aRadius
1471  return false;
1472  }
1473 
1474  return true;
1475 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:121
#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 123 of file drc.cpp.

124 {
125  if( m_drcDialog )
126  {
128 
129  m_drcDialog->Destroy();
130  m_drcDialog = NULL;
131  }
132 }
bool m_doCreateRptFile
Definition: drc.h:199
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:209
wxString m_rptFilename
Definition: drc.h:204

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 771 of file drc_clearance_test_functions.cpp.

772 {
773  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
774  return true;
775  // Get polygon, contour and vertex index.
777 
778  // If the vertex does not exist, there is no conflict
779  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
780  return true;
781 
782  // Retrieve the selected contour
783  SHAPE_LINE_CHAIN contour;
784  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
785 
786  // Retrieve the segment that starts at aCornerIndex-th corner.
787  SEG selectedSegment = contour.Segment( index.m_vertex );
788 
789  VECTOR2I start = selectedSegment.A;
790  VECTOR2I end = selectedSegment.B;
791 
792  // iterate through all areas
793  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
794  {
795  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
796  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
797  aArea->GetZoneClearance() );
798 
799  // test for same layer
800  if( area_to_test->GetLayer() != aArea->GetLayer() )
801  continue;
802 
803  // Test for same net
804  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
805  continue;
806 
807  // test for same priority
808  if( area_to_test->GetPriority() != aArea->GetPriority() )
809  continue;
810 
811  // test for same type
812  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
813  continue;
814 
815  // For keepout, there is no clearance, so use a minimal value for it
816  // use 1, not 0 as value to avoid some issues in tests
817  if( area_to_test->GetIsKeepout() )
818  zone_clearance = 1;
819 
820  // test for ending line inside area_to_test
821  if( area_to_test->Outline()->Contains( end ) )
822  {
823  wxPoint pos( end.x, end.y );
825  m_markerFactory.NewMarker( pos, aArea, area_to_test, DRCE_ZONES_INTERSECT );
826  return false;
827  }
828 
829  // now test spacing between areas
830  int ax1 = start.x;
831  int ay1 = start.y;
832  int ax2 = end.x;
833  int ay2 = end.y;
834 
835  // Iterate through all edges in the polygon.
837  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
838  {
839  SEG segment = *iterator;
840 
841  int bx1 = segment.A.x;
842  int by1 = segment.A.y;
843  int bx2 = segment.B.x;
844  int by2 = segment.B.y;
845 
846  int x, y; // variables containing the intersecting point coordinates
847  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
848  0,
849  ax1, ay1, ax2, ay2,
850  0,
851  zone_clearance,
852  &x, &y );
853 
854  if( d < zone_clearance )
855  {
856  // COPPERAREA_COPPERAREA error : edge intersect or too close
858  wxPoint( x, y ), aArea, area_to_test, DRCE_ZONES_TOO_CLOSE );
859  return false;
860  }
861 
862  }
863  }
864 
865  return true;
866 }
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:185
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
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:240
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
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:651
MARKER_PCB * m_currentMarker
Definition: drc.h:206
Definition: seg.h:36
SEG Segment(int aIndex)
Function Segment()
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:96
#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:952
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
int GetZoneClearance() const
Definition: class_zone.h:193
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:191
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 1476 of file drc.cpp.

1477 {
1478  DRC_COURTYARD_OVERLAP drc_overlap(
1479  m_markerFactory, [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1480 
1481  drc_overlap.RunDRC( *m_pcb );
1482 }
BOARD * m_pcb
Definition: drc.h:240
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
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:243

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 605 of file drc.cpp.

606 {
607  bool ret = true;
608 
610 
611 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
612 
613 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
614  if( nc->GetClearance() < g.m_MinClearance )
615  {
616  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
617  GetChars( nc->GetName() ),
618  FmtVal( nc->GetClearance() ),
619  FmtVal( g.m_TrackClearance )
620  );
621 
623  m_currentMarker = nullptr;
624  ret = false;
625  }
626 #endif
627 
628  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
629  {
630  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
631  GetChars( nc->GetName() ),
632  FmtVal( nc->GetTrackWidth() ),
634  );
635 
637  ret = false;
638  }
639 
640  if( nc->GetViaDiameter() < g.m_ViasMinSize )
641  {
642  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
643  GetChars( nc->GetName() ),
644  FmtVal( nc->GetViaDiameter() ),
645  FmtVal( g.m_ViasMinSize )
646  );
647 
649  ret = false;
650  }
651 
652  if( nc->GetViaDrill() < g.m_ViasMinDrill )
653  {
654  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
655  GetChars( nc->GetName() ),
656  FmtVal( nc->GetViaDrill() ),
658  );
659 
661  ret = false;
662  }
663 
664  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
665  {
666  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
667  GetChars( nc->GetName() ),
668  FmtVal( nc->GetuViaDiameter() ),
669  FmtVal( g.m_MicroViasMinSize ) );
670 
672  ret = false;
673  }
674 
675  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
676  {
677  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
678  GetChars( nc->GetName() ),
679  FmtVal( nc->GetuViaDrill() ),
681 
683  ret = false;
684  }
685 
686  return ret;
687 }
#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:534
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:80
BOARD * m_pcb
Definition: drc.h:240
#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:104
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:206
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:100
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
#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 1344 of file drc.cpp.

1345 {
1346  const static LSET all_cu = LSET::AllCuMask();
1347 
1348  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1349 
1350  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1351  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1352  * Therefore, this dummy pad is a circle or an oval.
1353  * A pad must have a parent because some functions expect a non null parent
1354  * to find the parent board, and some other data
1355  */
1356  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1357  D_PAD dummypad( &dummymodule );
1358 
1359  // Ensure the hole is on all copper layers
1360  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1361 
1362  // Use the minimal local clearance value for the dummy pad.
1363  // The clearance of the active pad will be used as minimum distance to a hole
1364  // (a value = 0 means use netclass value)
1365  dummypad.SetLocalClearance( 1 );
1366 
1367  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1368  {
1369  D_PAD* pad = *pad_list;
1370 
1371  if( pad == aRefPad )
1372  continue;
1373 
1374  // We can stop the test when pad->GetPosition().x > x_limit
1375  // because the list is sorted by X values
1376  if( pad->GetPosition().x > x_limit )
1377  break;
1378 
1379  // No problem if pads which are on copper layers are on different copper layers,
1380  // (pads can be only on a technical layer, to build complex pads)
1381  // but their hole (if any ) can create DRC error because they are on all
1382  // copper layers, so we test them
1383  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1384  ( pad->GetLayerSet() & all_cu ) != 0 &&
1385  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1386  {
1387  // if holes are in the same location and have the same size and shape,
1388  // this can be accepted
1389  if( pad->GetPosition() == aRefPad->GetPosition()
1390  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1391  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1392  {
1393  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1394  continue;
1395 
1396  // for oval holes: must also have the same orientation
1397  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1398  continue;
1399  }
1400 
1401  /* Here, we must test clearance between holes and pads
1402  * dummy pad size and shape is adjusted to pad drill size and shape
1403  */
1404  if( pad->GetDrillSize().x )
1405  {
1406  // pad under testing has a hole, test this hole against pad reference
1407  dummypad.SetPosition( pad->GetPosition() );
1408  dummypad.SetSize( pad->GetDrillSize() );
1409  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1411  dummypad.SetOrientation( pad->GetOrientation() );
1412 
1413  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1414  {
1415  // here we have a drc error on pad!
1417  return false;
1418  }
1419  }
1420 
1421  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1422  {
1423  dummypad.SetPosition( aRefPad->GetPosition() );
1424  dummypad.SetSize( aRefPad->GetDrillSize() );
1425  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1427  dummypad.SetOrientation( aRefPad->GetOrientation() );
1428 
1429  if( !checkClearancePadToPad( pad, &dummypad ) )
1430  {
1431  // here we have a drc error on aRefPad!
1433  return false;
1434  }
1435  }
1436 
1437  continue;
1438  }
1439 
1440  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1441  // But no problem if pads have the same netcode (same net)
1442  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1443  continue;
1444 
1445  // if pads are from the same footprint
1446  if( pad->GetParent() == aRefPad->GetParent() )
1447  {
1448  // and have the same pad number ( equivalent pads )
1449 
1450  // one can argue that this 2nd test is not necessary, that any
1451  // two pads from a single module are acceptable. This 2nd test
1452  // should eventually be a configuration option.
1453  if( pad->PadNameEqual( aRefPad ) )
1454  continue;
1455  }
1456 
1457  // if either pad has no drill and is only on technical layers, not a clearance violation
1458  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1459  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1460  {
1461  continue;
1462  }
1463 
1464  if( !checkClearancePadToPad( aRefPad, pad ) )
1465  {
1466  // here we have a drc error!
1468  return false;
1469  }
1470  }
1471 
1472  return true;
1473 }
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:209
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:221
BOARD * m_pcb
Definition: drc.h:240
Class LSET is a set of PCB_LAYER_IDs.
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:400
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:414
MODULE * GetParent() const
Definition: class_pad.h:164
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:206
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:394
const wxSize & GetDrillSize() const
Definition: class_pad.h:277
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
const wxPoint GetPosition() const override
Definition: class_pad.h:222
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  aTestPads,
bool  aTestZones 
)
private

Test the current segment.

Parameters
aRefSegThe segment to test
aStartthe first item of track list to test against (usually BOARD::m_Track)
aTestPadstrue if should do pads test
aTestZonestrue if should do copper zones test. This can be very time consumming
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( aTestPads )
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 copper zones */
709  /***************************************/
710  // Can be *very* time consumming.
711  if( aTestZones )
712  {
713  SEG refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
714 
715  for( ZONE_CONTAINER* zone : m_pcb->Zones() )
716  {
717  if( zone->GetFilledPolysList().IsEmpty() || zone->GetIsKeepout() )
718  continue;
719 
720  if( !( layerMask & zone->GetLayerSet() ).any() )
721  continue;
722 
723  if( zone->GetNetCode() && zone->GetNetCode() == net_code_ref )
724  continue;
725 
726  int clearance = zone->GetClearance( aRefSeg );
727  SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
728 
729  if( outline->Distance( refSeg, aRefSeg->GetWidth() ) < clearance )
731  }
732  }
733 
734  /***********************************************/
735  /* Phase 4: test DRC with to board edge */
736  /***********************************************/
737  {
738  SEG test_seg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
739 
740  int clearance = std::max( aRefSeg->GetClearance(), dsnSettings.m_CopperEdgeClearance );
741 
742  // the minimum distance = clearance plus half the reference track width
743  SEG::ecoord w_dist = clearance + aRefSeg->GetWidth() / 2;
744  w_dist *= w_dist;
745 
746  for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
747  {
748  if( test_seg.SquaredDistance( *it ) < w_dist )
749  {
750  auto pt = test_seg.NearestPoint( *it );
751  markers.push_back( m_markerFactory.NewMarker(
752  wxPoint( pt.x, pt.y ), aRefSeg, DRCE_TRACK_NEAR_EDGE ) );
753 
754  if( !handleNewMarker() )
755  return false;
756  }
757  }
758  }
759 
760 
761  if( markers.size() > 0 )
762  {
763  commitMarkers();
764  return false;
765  }
766  else
767  return true;
768 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:121
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:235
const wxPoint & GetStart() const
Definition: class_track.h:133
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:237
#define DRCE_TRACK_NEAR_PAD
pad too close to track
Definition: drc.h:51
int m_segmLength
Definition: drc.h:229
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:534
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
wxPoint m_padToTestPos
Definition: drc.h:220
#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:240
#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:104
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint GetPosition() const override
Definition: class_track.h:124
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:400
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:414
#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:437
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:201
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc.h:236
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:239
string & err
Definition: json11.cpp:598
const wxPoint GetPosition() const override
Definition: class_track.h:410
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:221
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:241
ZONE_CONTAINERS & Zones()
Definition: class_board.h:254
int GetWidth() const
Definition: class_track.h:127
TRACK * Next() const
Definition: class_track.h:110
#define max(a, b)
Definition: auxiliary.h:86
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:394
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:277
wxPoint ShapePos() const
Definition: class_pad.cpp:562
#define DRCE_VIA_NEAR_TRACK
via too close to track
Definition: drc.h:54
const wxPoint & GetEnd() const
Definition: class_track.h:130
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:243
const wxPoint GetPosition() const override
Definition: class_pad.h:222
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:214
int m_xcliplo
Definition: drc.h:234
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:228
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:204
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, BOARD_DESIGN_SETTINGS::m_CopperEdgeClearance, 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, max, 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 1295 of file drc.cpp.

1296 {
1297  // Test keepout areas for vias, tracks and pads inside keepout areas
1298  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
1299  {
1300  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
1301 
1302  if( !area->GetIsKeepout() )
1303  continue;
1304 
1305  if( aRefSeg->Type() == PCB_TRACE_T )
1306  {
1307  if( !area->GetDoNotAllowTracks() )
1308  continue;
1309 
1310  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
1311  continue;
1312 
1313  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
1314  aRefSeg->GetWidth() ) == 0 )
1315  {
1316  m_currentMarker =
1318  return false;
1319  }
1320  }
1321  else if( aRefSeg->Type() == PCB_VIA_T )
1322  {
1323  if( !area->GetDoNotAllowVias() )
1324  continue;
1325 
1326  auto viaLayers = aRefSeg->GetLayerSet();
1327 
1328  if( !area->CommonLayerExists( viaLayers ) )
1329  continue;
1330 
1331  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1332  {
1333  m_currentMarker =
1335  return false;
1336  }
1337  }
1338  }
1339 
1340  return true;
1341 }
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:204
const wxPoint & GetStart() const
Definition: class_track.h:133
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:278
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
#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:240
bool GetDoNotAllowVias() const
Definition: class_zone.h:653
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
const wxPoint GetPosition() const override
Definition: class_track.h:124
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:651
MARKER_PCB * m_currentMarker
Definition: drc.h:206
Definition: seg.h:36
int GetWidth() const
Definition: class_track.h:127
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:130
bool GetDoNotAllowTracks() const
Definition: class_zone.h:654
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:952
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
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:204

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 181 of file drc.cpp.

182 {
183  updatePointers();
184 
185  // Set right options for this on line drc
186  int drc_state = m_drcInLegacyRoutingMode;
188  int rpt_state = m_reportAllTrackErrors;
189  m_reportAllTrackErrors = false;
190 
191  // Test new segment against tracks and pads, not against copper zones
192  if( !doTrackDrc( aRefSegm, aList, true, false ) )
193  {
194  if( m_currentMarker )
195  {
197  delete m_currentMarker;
198  m_currentMarker = nullptr;
199  }
200 
201  m_drcInLegacyRoutingMode = drc_state;
202  m_reportAllTrackErrors = rpt_state;
203  return BAD_DRC;
204  }
205 
206  if( !doTrackKeepoutDrc( aRefSegm ) )
207  {
208  if( m_currentMarker )
209  {
211  delete m_currentMarker;
212  m_currentMarker = nullptr;
213  }
214 
215  m_drcInLegacyRoutingMode = drc_state;
216  m_reportAllTrackErrors = rpt_state;
217  return BAD_DRC;
218  }
219 
220  m_drcInLegacyRoutingMode = drc_state;
221  m_reportAllTrackErrors = rpt_state;
222  return OK_DRC;
223 }
#define OK_DRC
Definition: drc.h:39
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:1295
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool aTestPads, bool aTestZones)
Test the current segment.
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:586
bool m_reportAllTrackErrors
Definition: drc.h:201
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
#define BAD_DRC
Definition: drc.h:40
MARKER_PCB * m_currentMarker
Definition: drc.h:206
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:214

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 379 of file drc.cpp.

380 {
381  updatePointers();
382 
383  // Set right options for this on line drc
384  int drc_state = m_drcInLegacyRoutingMode;
386  int rpt_state = m_reportAllTrackErrors;
387  m_reportAllTrackErrors = false;
388 
389  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
390  {
391  wxASSERT( m_currentMarker );
393  delete m_currentMarker;
394  m_currentMarker = nullptr;
395  m_drcInLegacyRoutingMode = drc_state;
396  m_reportAllTrackErrors = rpt_state;
397  return BAD_DRC;
398  }
399 
400  m_drcInLegacyRoutingMode = drc_state;
401  m_reportAllTrackErrors = rpt_state;
402  return OK_DRC;
403 }
#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:586
bool m_reportAllTrackErrors
Definition: drc.h:201
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
#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:206
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message,...
Definition: drc.h:214

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 504 of file drc.h.

505  {
506  return m_currentMarker;
507  }
MARKER_PCB * m_currentMarker
Definition: drc.h:206

References m_currentMarker.

Referenced by PCB_EDIT_FRAME::Other_Layer_Route().

◆ 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 406 of file drc.cpp.

407 {
408  // be sure m_pcb is the current board, not a old one
409  // ( the board can be reloaded )
411 
412  if( aMessages )
413  {
414  aMessages->AppendText( _( "Board Outline...\n" ) );
415  wxSafeYield();
416  }
417 
418  testOutline();
419 
420  // someone should have cleared the two lists before calling this.
421  if( !testNetClasses() )
422  {
423  // testing the netclasses is a special case because if the netclasses
424  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
425  // class (a NET) will cause its items such as tracks, vias, and pads
426  // to also fail. So quit after *all* netclass errors have been reported.
427  if( aMessages )
428  aMessages->AppendText( _( "Aborting\n" ) );
429 
430  // update the m_drcDialog listboxes
431  updatePointers();
432 
433  return;
434  }
435 
436  // test pad to pad clearances, nothing to do with tracks, vias or zones.
437  if( m_doPad2PadTest )
438  {
439  if( aMessages )
440  {
441  aMessages->AppendText( _( "Pad clearances...\n" ) );
442  wxSafeYield();
443  }
444 
445  testPad2Pad();
446  }
447 
448  // test clearances between drilled holes
449  if( aMessages )
450  {
451  aMessages->AppendText( _( "Drill clearances...\n" ) );
452  wxSafeYield();
453  }
454 
456 
457  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
458  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
459 
460  if( m_refillZones )
461  {
462  if( aMessages )
463  aMessages->AppendText( _( "Refilling all zones...\n" ) );
464 
466  }
467  else
468  {
469  if( aMessages )
470  aMessages->AppendText( _( "Checking zone fills...\n" ) );
471 
473  }
474 
475  // test track and via clearances to other tracks, pads, and vias
476  if( aMessages )
477  {
478  aMessages->AppendText( _( "Track clearances...\n" ) );
479  wxSafeYield();
480  }
481 
482  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
483 
484  // test zone clearances to other zones
485  if( aMessages )
486  {
487  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
488  wxSafeYield();
489  }
490 
491  testZones();
492 
493  // find and gather unconnected pads.
494  if( m_doUnconnectedTest )
495  {
496  if( aMessages )
497  {
498  aMessages->AppendText( _( "Unconnected pads...\n" ) );
499  aMessages->Refresh();
500  }
501 
502  testUnconnected();
503  }
504 
505  // find and gather vias, tracks, pads inside keepout areas.
506  if( m_doKeepoutTest )
507  {
508  if( aMessages )
509  {
510  aMessages->AppendText( _( "Keepout areas ...\n" ) );
511  aMessages->Refresh();
512  }
513 
515  }
516 
517  // find and gather vias, tracks, pads inside text boxes.
518  if( aMessages )
519  {
520  aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
521  wxSafeYield();
522  }
523 
525 
526  // find overlapping courtyard ares.
529  {
530  if( aMessages )
531  {
532  aMessages->AppendText( _( "Courtyard areas...\n" ) );
533  aMessages->Refresh();
534  }
535 
537  }
538 
539  for( DRC_ITEM* footprintItem : m_footprints )
540  delete footprintItem;
541 
542  m_footprints.clear();
543  m_footprintsTested = false;
544 
545  if( m_testFootprints && !Kiface().IsSingle() )
546  {
547  if( aMessages )
548  {
549  aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
550  aMessages->Refresh();
551  }
552 
553  NETLIST netlist;
555 
556  if( m_drcDialog )
557  m_drcDialog->Raise();
558 
560  m_footprintsTested = true;
561  }
562 
563  // Check if there are items on disabled layers
565 
566  if( aMessages )
567  {
568  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
569  aMessages->Refresh();
570  }
571 
572  m_drcRun = true;
573 
574  // update the m_drcDialog listboxes
575  updatePointers();
576 
577  if( aMessages )
578  {
579  // no newline on this one because it is last, don't want the window
580  // to unnecessarily scroll.
581  aMessages->AppendText( _( "Finished" ) );
582  }
583 }
bool m_refillZones
Definition: drc.h:200
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
void testCopperTextAndGraphics()
Definition: drc.cpp:1007
DRC_LIST m_footprints
list of footprint warnings, as DRC_ITEMs
Definition: drc.h:246
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
void testKeepoutAreas()
Definition: drc.cpp:958
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:534
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
Definition: drc.cpp:1244
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
Definition: kicad.cpp:52
BOARD * m_pcb
Definition: drc.h:240
static void TestFootprints(NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS_T aUnits, DRC_LIST &aDRCList)
Test the board footprints against a netlist.
Definition: drc.cpp:1485
void testDrilledHoles()
Definition: drc.cpp:757
bool m_testFootprints
Definition: drc.h:202
bool m_doKeepoutTest
Definition: drc.h:198
Class NETLIST stores all of information read from a netlist along with the flags used to update the N...
Definition: pcb_netlist.h:214
void testZones()
Definition: drc.cpp:922
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:586
bool m_drcRun
Definition: drc.h:247
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
Definition: drc.cpp:1258
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
bool m_doPad2PadTest
Definition: drc.h:195
void testPad2Pad()
Definition: drc.cpp:713
void Fill_All_Zones()
Function Fill_All_Zones.
bool m_footprintsTested
Definition: drc.h:248
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:690
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
Definition: drc.cpp:830
BOARD * GetBoard() const
void testUnconnected()
Definition: drc.cpp:890
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
bool m_doUnconnectedTest
Definition: drc.h:196
void doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1476
EDA_UNITS_T GetUserUnits() const override
Definition: dialog_shim.h:133

References PCB_EDIT_FRAME::ANNOTATION_DIALOG, PCB_EDIT_FRAME::Check_All_Zones(), doFootprintOverlappingDrc(), PCB_EDIT_FRAME::FetchNetlistFromSchematic(), PCB_EDIT_FRAME::Fill_All_Zones(), PCB_BASE_FRAME::GetBoard(), BOARD::GetDesignSettings(), DIALOG_SHIM::GetUserUnits(), Kiface(), m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_drcDialog, m_drcRun, m_footprints, m_footprintsTested, m_pcb, m_pcbEditorFrame, BOARD_DESIGN_SETTINGS::m_ProhibitOverlappingCourtyards, m_refillZones, BOARD_DESIGN_SETTINGS::m_RequireCourtyards, m_testFootprints, testCopperTextAndGraphics(), testDisabledLayers(), testDrilledHoles(), TestFootprints(), testKeepoutAreas(), testNetClasses(), testOutline(), testPad2Pad(), testTracks(), testUnconnected(), testZones(), and updatePointers().

Referenced by 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 65 of file drc.cpp.

66 {
67  bool show_dlg_modal = true;
68 
69  // the dialog needs a parent frame. if it is not specified, this is
70  // the PCB editor frame specified in DRC class.
71  if( aParent == NULL )
72  {
73  // if any parent is specified, the dialog is modal.
74  // if this is the default PCB editor frame, it is not modal
75  show_dlg_modal = false;
76  aParent = m_pcbEditorFrame;
77  }
78 
80  toolMgr->RunAction( ACTIONS::cancelInteractive, true );
81  toolMgr->DeactivateTool();
82  toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
83 
84  if( !m_drcDialog )
85  {
86  m_drcDialog = new DIALOG_DRC_CONTROL( this, m_pcbEditorFrame, aParent );
88 
90 
91  if( show_dlg_modal )
92  m_drcDialog->ShowModal();
93  else
94  m_drcDialog->Show( true );
95  }
96  else // The dialog is just not visible (because the user has double clicked on an error item)
97  {
99  m_drcDialog->Show( true );
100  }
101 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool m_doCreateRptFile
Definition: drc.h:199
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
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.
Class TOOL_MANAGER.
Definition: tool_manager.h:49
TOOL_MANAGER * GetToolManager() const override
Return the tool manager instance, if any.
Definition: draw_frame.h:937
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:586
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
bool Show(bool show) override
friend class DIALOG_DRC_CONTROL
Definition: drc.h:190
wxString m_rptFilename
Definition: drc.h:204
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:202

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 1050 of file drc.cpp.

1051 {
1052  std::vector<SEG> itemShape;
1053  int itemWidth = aItem->GetWidth();
1054 
1055  switch( aItem->GetShape() )
1056  {
1057  case S_ARC:
1058  {
1059  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
1060 
1061  auto l = arc.ConvertToPolyline();
1062 
1063  for( int i = 0; i < l.SegmentCount(); i++ )
1064  itemShape.push_back( l.CSegment(i) );
1065 
1066  break;
1067  }
1068 
1069  case S_SEGMENT:
1070  itemShape.push_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
1071  break;
1072 
1073  case S_CIRCLE:
1074  {
1075  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
1076  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1077 
1078  auto l = circle.ConvertToPolyline();
1079 
1080  for( int i = 0; i < l.SegmentCount(); i++ )
1081  itemShape.push_back( l.CSegment(i) );
1082 
1083  break;
1084  }
1085 
1086  case S_CURVE:
1087  {
1088  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1089  wxPoint start_pt = aItem->GetBezierPoints()[0];
1090 
1091  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1092  {
1093  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1094  itemShape.push_back( SEG( start_pt, end_pt ) );
1095  start_pt = end_pt;
1096  }
1097 
1098  break;
1099  }
1100 
1101  default:
1102  break;
1103  }
1104 
1105  // Test tracks and vias
1106  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1107  {
1108  if( !track->IsOnLayer( aItem->GetLayer() ) )
1109  continue;
1110 
1111  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1112  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1113 
1114  for( const auto& itemSeg : itemShape )
1115  {
1116  if( trackAsSeg.Distance( itemSeg ) < minDist )
1117  {
1118  if( track->Type() == PCB_VIA_T )
1120  track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1121  else
1123  track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1124  break;
1125  }
1126  }
1127  }
1128 
1129  // Test pads
1130  for( auto pad : m_pcb->GetPads() )
1131  {
1132  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1133  continue;
1134 
1135  // Graphic items are allowed to act as net-ties within their own footprint
1136  if( pad->GetParent() == aItem->GetParent() )
1137  continue;
1138 
1139  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1140  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1141  SHAPE_POLY_SET padOutline;
1142 
1143  // We incorporate "minDist" into the pad's outline
1144  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ),
1145  segmentCount, correctionFactor );
1146 
1147  for( const auto& itemSeg : itemShape )
1148  {
1149  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1150  {
1152  break;
1153  }
1154  }
1155  }
1156 }
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:240
#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:104
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:249
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
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 1007 of file drc.cpp.

1008 {
1009  // Test copper items for clearance violations with vias, tracks and pads
1010 
1011  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
1012  {
1013  if( IsCopperLayer( brdItem->GetLayer() ) )
1014  {
1015  if( brdItem->Type() == PCB_TEXT_T )
1016  testCopperTextItem( brdItem );
1017  else if( brdItem->Type() == PCB_LINE_T )
1018  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
1019  }
1020  }
1021 
1022  for( MODULE* module : m_pcb->Modules() )
1023  {
1024  TEXTE_MODULE& ref = module->Reference();
1025  TEXTE_MODULE& val = module->Value();
1026 
1027  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
1028  testCopperTextItem( &ref );
1029 
1030  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
1031  testCopperTextItem( &val );
1032 
1033  if( module->IsNetTie() )
1034  continue;
1035 
1036  for( BOARD_ITEM* item = module->GraphicalItemsList(); item; item = item->Next() )
1037  {
1038  if( IsCopperLayer( item->GetLayer() ) )
1039  {
1040  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
1041  testCopperTextItem( item );
1042  else if( item->Type() == PCB_MODULE_EDGE_T )
1043  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
1044  }
1045  }
1046  }
1047 }
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:193
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
Definition: drc.cpp:1050
void testCopperTextItem(BOARD_ITEM *aTextItem)
Definition: drc.cpp:1159
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
BOARD * m_pcb
Definition: drc.h:240
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:252
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:253

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 1159 of file drc.cpp.

1160 {
1161  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1162 
1163  if( text == nullptr )
1164  return;
1165 
1166  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1167  int textWidth = text->GetThickness();
1168 
1169  // So far the bounding box makes up the text-area
1170  text->TransformTextShapeToSegmentList( textShape );
1171 
1172  if( textShape.size() == 0 ) // Should not happen (empty text?)
1173  return;
1174 
1175  EDA_RECT bbox = text->GetTextBox();
1176  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1177 
1178  // Test tracks and vias
1179  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1180  {
1181  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1182  continue;
1183 
1184  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1185  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1186 
1187  // Fast test to detect a trach segment candidate inside the text bounding box
1188  if( !rect_area.Collide( trackAsSeg, minDist ) )
1189  continue;
1190 
1191  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1192  {
1193  SEG textSeg( textShape[jj], textShape[jj+1] );
1194 
1195  if( trackAsSeg.Distance( textSeg ) < minDist )
1196  {
1197  if( track->Type() == PCB_VIA_T )
1199  track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1200  else
1202  track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
1203  break;
1204  }
1205  }
1206  }
1207 
1208  // Test pads
1209  for( auto pad : m_pcb->GetPads() )
1210  {
1211  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1212  continue;
1213 
1214  // Fast test to detect a pad candidate inside the text bounding box
1215  // Finer test (time consumming) is made only for pads near the text.
1216  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1217  VECTOR2I shape_pos( pad->ShapePos() );
1218 
1219  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1220  continue;
1221 
1222  const int segmentCount = ARC_APPROX_SEGMENTS_COUNT_HIGH_DEF;
1223  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1224  SHAPE_POLY_SET padOutline;
1225 
1226  int minDist = textWidth/2 + pad->GetClearance( NULL );
1227  pad->TransformShapeWithClearanceToPolygon( padOutline, 0,
1228  segmentCount, correctionFactor );
1229 
1230  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1231  {
1232  SEG textSeg( textShape[jj], textShape[jj+1] );
1233 
1234  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1235  {
1237  break;
1238  }
1239  }
1240  }
1241 }
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:171
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:89
BOARD * m_pcb
Definition: drc.h:240
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:128
#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:104
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:119
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:496
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:249
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
#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 1258 of file drc.cpp.

1259 {
1260  BOARD* board = m_pcbEditorFrame->GetBoard();
1261  wxCHECK( board, /*void*/ );
1262  LSET disabledLayers = board->GetEnabledLayers().flip();
1263 
1264  // Perform the test only for copper layers
1265  disabledLayers &= LSET::AllCuMask();
1266 
1267  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1269  aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1270  };
1271 
1272  for( auto track : board->Tracks() )
1273  {
1274  if( disabledLayers.test( track->GetLayer() ) )
1275  createMarker( track );
1276  }
1277 
1278  for( auto module : board->Modules() )
1279  {
1280  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1281  {
1282  if( disabledLayers.test( aItem->GetLayer() ) )
1283  createMarker( aItem );
1284  } );
1285  }
1286 
1287  for( auto zone : board->Zones() )
1288  {
1289  if( disabledLayers.test( zone->GetLayer() ) )
1290  createMarker( zone );
1291  }
1292 }
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:104
Class LSET is a set of PCB_LAYER_IDs.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:252
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:239
ZONE_CONTAINERS & Zones()
Definition: class_board.h:254
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:251
BOARD * GetBoard() const
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
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 757 of file drc.cpp.

758 {
759  int holeToHoleMin = m_pcb->GetDesignSettings().m_HoleToHoleMin;
760 
761  if( holeToHoleMin == 0 ) // No min setting turns testing off.
762  return;
763 
764  // Test drilled hole clearances to minimize drill bit breakage.
765  //
766  // Notes: slots are milled, so we're only concerned with circular holes
767  // microvias are laser-drilled, so we're only concerned with standard vias
768 
769  struct DRILLED_HOLE
770  {
771  wxPoint m_location;
772  int m_drillRadius;
773  BOARD_ITEM* m_owner;
774  };
775 
776  std::vector<DRILLED_HOLE> holes;
777  DRILLED_HOLE hole;
778 
779  for( MODULE* mod : m_pcb->Modules() )
780  {
781  for( D_PAD* pad : mod->Pads( ) )
782  {
783  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
784  {
785  hole.m_location = pad->GetPosition();
786  hole.m_drillRadius = pad->GetDrillSize().x / 2;
787  hole.m_owner = pad;
788  holes.push_back( hole );
789  }
790  }
791  }
792 
793  for( TRACK* track : m_pcb->Tracks() )
794  {
795  VIA* via = dynamic_cast<VIA*>( track );
796  if( via && via->GetViaType() == VIA_THROUGH )
797  {
798  hole.m_location = via->GetPosition();
799  hole.m_drillRadius = via->GetDrillValue() / 2;
800  hole.m_owner = via;
801  holes.push_back( hole );
802  }
803  }
804 
805  for( size_t ii = 0; ii < holes.size(); ++ii )
806  {
807  const DRILLED_HOLE& refHole = holes[ ii ];
808 
809  for( size_t jj = ii + 1; jj < holes.size(); ++jj )
810  {
811  const DRILLED_HOLE& checkHole = holes[ jj ];
812 
813  // Holes with identical locations are allowable
814  if( checkHole.m_location == refHole.m_location )
815  continue;
816 
817  if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
818  < checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
819  {
821  DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
822  refHole.m_owner, refHole.m_location,
823  checkHole.m_owner, checkHole.m_location ) );
824  }
825  }
826  }
827 }
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:200
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:118
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:534
BOARD * m_pcb
Definition: drc.h:240
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
int m_HoleToHoleMin
Min width of peninsula between two drilled holes.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:252
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:289
VIATYPE_T GetViaType() const
Definition: class_track.h:437
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
const wxPoint GetPosition() const override
Definition: class_track.h:410
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:251
#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().

◆ TestFootprints()

void DRC::TestFootprints ( NETLIST aNetlist,
BOARD aPCB,
EDA_UNITS_T  aUnits,
DRC_LIST aDRCList 
)
static

Test the board footprints against a netlist.

Will report DRCE_MISSING_FOOTPRINT, DRCE_DUPLICATE_FOOTPRINT and DRCE_EXTRA_FOOTPRINT errors in aDRCList.

Definition at line 1485 of file drc.cpp.

1487 {
1488  MODULE* module;
1489  MODULE* nextModule;
1490 
1491  // Search for duplicate footprints.
1492  for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
1493  {
1494  nextModule = module->Next();
1495 
1496  for( ; nextModule != NULL; nextModule = nextModule->Next() )
1497  {
1498  if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
1499  {
1500  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_DUPLICATE_FOOTPRINT,
1501  module, module->GetPosition(),
1502  nextModule, nextModule->GetPosition() ) );
1503  break;
1504  }
1505  }
1506  }
1507 
1508  // Search for component footprints in the netlist but not on the board.
1509  for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
1510  {
1511  COMPONENT* component = aNetlist.GetComponent( ii );
1512 
1513  module = aPCB->FindModuleByReference( component->GetReference() );
1514 
1515  if( module == NULL )
1516  {
1517  wxString msg = wxString::Format( wxT( "%s (%s)" ),
1518  component->GetReference(),
1519  component->GetValue() );
1520 
1521  aDRCList.emplace_back( new DRC_ITEM( DRCE_MISSING_FOOTPRINT, msg ) );
1522  }
1523  }
1524 
1525  // Search for component footprints found on board but not in netlist.
1526  for( module = aPCB->m_Modules; module != NULL; module = module->Next() )
1527  {
1528 
1529  COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
1530 
1531  if( component == NULL )
1532  {
1533  aDRCList.emplace_back( new DRC_ITEM( aUnits, DRCE_EXTRA_FOOTPRINT,
1534  module, module->GetPosition(),
1535  nullptr, wxPoint() ) );
1536  }
1537  }
1538 }
#define DRCE_EXTRA_FOOTPRINT
netlist item not found for footprint
Definition: drc.h:104
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item.
Definition: drc_item.h:48
#define DRCE_MISSING_FOOTPRINT
footprint not found for netlist item
Definition: drc.h:102
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:256
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:462
#define DRCE_DUPLICATE_FOOTPRINT
more than one footprints found for netlist item
Definition: drc.h:103
const wxString & GetReference() const
Definition: pcb_netlist.h:151
Class COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:83
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:265
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
DLIST< MODULE > m_Modules
Definition: class_board.h:248
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
MODULE * Next() const
Definition: class_module.h:122
const wxString & GetValue() const
Definition: pcb_netlist.h:153
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
const wxPoint GetPosition() const override
Definition: class_module.h:183

References DRCE_DUPLICATE_FOOTPRINT, DRCE_EXTRA_FOOTPRINT, DRCE_MISSING_FOOTPRINT, BOARD::FindModuleByReference(), Format(), NETLIST::GetComponent(), NETLIST::GetComponentByReference(), NETLIST::GetCount(), MODULE::GetPosition(), COMPONENT::GetReference(), MODULE::GetReference(), COMPONENT::GetValue(), BOARD::m_Modules, and MODULE::Next().

Referenced by DIALOG_NETLIST::OnTestFootprintsClick(), and RunTests().

◆ testKeepoutAreas()

void DRC::testKeepoutAreas ( )
private

Definition at line 958 of file drc.cpp.

959 {
960  // Test keepout areas for vias, tracks and pads inside keepout areas
961  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
962  {
963  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
964 
965  if( !area->GetIsKeepout() )
966  {
967  continue;
968  }
969 
970  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
971  {
972  if( segm->Type() == PCB_TRACE_T )
973  {
974  if( !area->GetDoNotAllowTracks() )
975  continue;
976 
977  // Ignore if the keepout zone is not on the same layer
978  if( !area->IsOnLayer( segm->GetLayer() ) )
979  continue;
980 
981  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
982 
983  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
986  }
987  else if( segm->Type() == PCB_VIA_T )
988  {
989  if( ! area->GetDoNotAllowVias() )
990  continue;
991 
992  auto viaLayers = segm->GetLayerSet();
993 
994  if( !area->CommonLayerExists( viaLayers ) )
995  continue;
996 
997  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
1000  }
1001  }
1002  // Test pads: TODO
1003  }
1004 }
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:204
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:278
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:260
#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:240
bool GetDoNotAllowVias() const
Definition: class_zone.h:653
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
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:651
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:654
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:249
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:952
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243

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 690 of file drc.cpp.

691 {
692  bool ret = true;
693 
695 
696  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
697 
698  if( !doNetClass( netclasses.GetDefault(), msg ) )
699  ret = false;
700 
701  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
702  {
703  NETCLASSPTR nc = i->second;
704 
705  if( !doNetClass( nc, msg ) )
706  ret = false;
707  }
708 
709  return ret;
710 }
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
Definition: drc.cpp:605
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:534
iterator end()
Definition: netclass.h:249
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:251
BOARD * m_pcb
Definition: drc.h:240
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 1244 of file drc.cpp.

1245 {
1246  wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
1247 
1249 
1250  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1251  {
1253  return;
1254  }
1255 }
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:802
BOARD * m_pcb
Definition: drc.h:240
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
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:241
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243

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

Referenced by RunTests().

◆ testPad2Pad()

void DRC::testPad2Pad ( )
private

Definition at line 713 of file drc.cpp.

714 {
715  std::vector<D_PAD*> sortedPads;
716 
717  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
718 
719  if( sortedPads.size() == 0 )
720  return;
721 
722  // find the max size of the pads (used to stop the test)
723  int max_size = 0;
724 
725  for( unsigned i = 0; i < sortedPads.size(); ++i )
726  {
727  D_PAD* pad = sortedPads[i];
728 
729  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
730  int radius = pad->GetBoundingRadius();
731 
732  if( radius > max_size )
733  max_size = radius;
734  }
735 
736  // Upper limit of pad list (limit not included)
737  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
738 
739  // Test the pads
740  for( unsigned i = 0; i< sortedPads.size(); ++i )
741  {
742  D_PAD* pad = sortedPads[i];
743 
744  int x_limit = max_size + pad->GetClearance() +
745  pad->GetBoundingRadius() + pad->GetPosition().x;
746 
747  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
748  {
749  wxASSERT( m_currentMarker );
751  m_currentMarker = nullptr;
752  }
753  }
754 }
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:240
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:624
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:1344
MARKER_PCB * m_currentMarker
Definition: drc.h:206
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:608
const wxPoint GetPosition() const override
Definition: class_pad.h:222

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 830 of file drc.cpp.

831 {
832  wxProgressDialog * progressDialog = NULL;
833  const int delta = 500; // This is the number of tests between 2 calls to the
834  // progress bar
835  int count = 0;
836 
837  for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
838  count++;
839 
840  int deltamax = count/delta;
841 
842  if( aShowProgressBar && deltamax > 3 )
843  {
844  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
845  // on OSX
846  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
847  deltamax, aActiveWindow,
848  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
849  progressDialog->Update( 0, wxEmptyString );
850  }
851 
852  int ii = 0;
853  count = 0;
854 
855  for( TRACK* segm = m_pcb->m_Track; segm; segm = segm->Next() )
856  {
857  if( ii++ > delta )
858  {
859  ii = 0;
860  count++;
861 
862  if( progressDialog )
863  {
864  if( !progressDialog->Update( count, wxEmptyString ) )
865  break; // Aborted by user
866 #ifdef __WXMAC__
867  // Work around a dialog z-order issue on OS X
868  if( count == deltamax )
869  aActiveWindow->Raise();
870 #endif
871  }
872  }
873 
874  // Test new segment against tracks and pads, optionally against copper zones
875  if( !doTrackDrc( segm, segm->Next(), true, m_doZonesTest ) )
876  {
877  if( m_currentMarker )
878  {
880  m_currentMarker = nullptr;
881  }
882  }
883  }
884 
885  if( progressDialog )
886  progressDialog->Destroy();
887 }
static const int delta[8][2]
Definition: solve.cpp:112
BOARD * m_pcb
Definition: drc.h:240
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool aTestPads, bool aTestZones)
Test the current segment.
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
bool m_doZonesTest
Definition: drc.h:197
MARKER_PCB * m_currentMarker
Definition: drc.h:206
DLIST< TRACK > m_Track
Definition: class_board.h:249

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

Referenced by RunTests().

◆ testUnconnected()

void DRC::testUnconnected ( )
private

Definition at line 890 of file drc.cpp.

891 {
892  for( DRC_ITEM* unconnectedItem : m_unconnected )
893  delete unconnectedItem;
894 
895  m_unconnected.clear();
896 
897  auto connectivity = m_pcb->GetConnectivity();
898 
899  connectivity->Clear();
900  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
901  connectivity->RecalculateRatsnest();
902 
903  std::vector<CN_EDGE> edges;
904  connectivity->GetUnconnectedEdges( edges );
905 
906  for( const auto& edge : edges )
907  {
908  auto src = edge.GetSourcePos();
909  auto dst = edge.GetTargetPos();
910 
911  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
913  edge.GetSourceNode()->Parent(),
914  wxPoint( src.x, src.y ),
915  edge.GetTargetNode()->Parent(),
916  wxPoint( dst.x, dst.y ) ) );
917 
918  }
919 }
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:240
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:289
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:292
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:245

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

Referenced by RunTests().

◆ testZones()

void DRC::testZones ( )
private

Definition at line 922 of file drc.cpp.

923 {
924  // Test copper areas for valid netcodes
925  // if a netcode is < 0 the netname was not found when reading a netlist
926  // if a netcode is == 0 the netname is void, and the zone is not connected.
927  // This is allowed, but i am not sure this is a good idea
928  //
929  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
930  // is stored, and initialized from the file or the zone properties editor.
931  // if it differs from the net name from net code, there is a DRC issue
932  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
933  {
934  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
935 
936  if( !zone->IsOnCopperLayer() )
937  continue;
938 
939  int netcode = zone->GetNetCode();
940  // a netcode < 0 or > 0 and no pad in net is a error or strange
941  // perhaps a "dead" net, which happens when all pads in this net were removed
942  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
943  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
944 
945  if( ( netcode < 0 ) || pads_in_net == 0 )
946  {
947  wxPoint markerPos = zone->GetPosition();
949  markerPos, zone, DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE ) );
950  }
951  }
952 
953  // Test copper areas outlines, and create markers when needed
954  TestZoneToZoneOutline( NULL, true );
955 }
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:226
const wxPoint GetPosition() const override
Definition: class_zone.cpp:179
#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:240
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:104
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
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:292
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:952
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:191

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 226 of file drc.cpp.

227 {
228  BOARD* board = m_pcbEditorFrame->GetBoard();
229  BOARD_COMMIT commit( m_pcbEditorFrame );
230  int nerrors = 0;
231 
232  std::vector<SHAPE_POLY_SET> smoothed_polys;
233  smoothed_polys.resize( board->GetAreaCount() );
234 
235  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
236  {
237  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
238  zoneRef->BuildSmoothedPoly( smoothed_polys[ia] );
239  }
240 
241  // iterate through all areas
242  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
243  {
244  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
245 
246  if( !zoneRef->IsOnCopperLayer() )
247  continue;
248 
249  // When testing only a single area, skip all others
250  if( aZone && ( aZone != zoneRef) )
251  continue;
252 
253  // If we are testing a single zone, then iterate through all other zones
254  // Otherwise, we have already tested the zone combination
255  for( int ia2 = ( aZone ? 0 : ia + 1 ); ia2 < board->GetAreaCount(); ia2++ )
256  {
257  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
258 
259  if( zoneRef == zoneToTest )
260  continue;
261 
262  // test for same layer
263  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
264  continue;
265 
266  // Test for same net
267  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
268  continue;
269 
270  // test for different priorities
271  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
272  continue;
273 
274  // test for different types
275  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
276  continue;
277 
278  // Examine a candidate zone: compare zoneToTest to zoneRef
279 
280  // Get clearance used in zone to zone test. The policy used to
281  // obtain that value is now part of the zone object itself by way of
282  // ZONE_CONTAINER::GetClearance().
283  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
284 
285  // Keepout areas have no clearance, so set zone2zoneClearance to 1
286  // ( zone2zoneClearance = 0 can create problems in test functions)
287  if( zoneRef->GetIsKeepout() )
288  zone2zoneClearance = 1;
289 
290  // test for some corners of zoneRef inside zoneToTest
291  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
292  {
293  VECTOR2I currentVertex = *iterator;
294  wxPoint pt( currentVertex.x, currentVertex.y );
295 
296  if( smoothed_polys[ia2].Contains( currentVertex ) )
297  {
298  if( aCreateMarkers )
299  commit.Add( m_markerFactory.NewMarker(
300  pt, zoneRef, zoneToTest, DRCE_ZONES_INTERSECT ) );
301 
302  nerrors++;
303  }
304  }
305 
306  // test for some corners of zoneToTest inside zoneRef
307  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
308  {
309  VECTOR2I currentVertex = *iterator;
310  wxPoint pt( currentVertex.x, currentVertex.y );
311 
312  if( smoothed_polys[ia].Contains( currentVertex ) )
313  {
314  if( aCreateMarkers )
315  commit.Add( m_markerFactory.NewMarker(
316  pt, zoneToTest, zoneRef, DRCE_ZONES_INTERSECT ) );
317 
318  nerrors++;
319  }
320  }
321 
322  // Iterate through all the segments of refSmoothedPoly
323  std::set<wxPoint> conflictPoints;
324 
325  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
326  {
327  // Build ref segment
328  SEG refSegment = *refIt;
329 
330  // Iterate through all the segments in smoothed_polys[ia2]
331  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
332  {
333  // Build test segment
334  SEG testSegment = *testIt;
335  wxPoint pt;
336 
337  int ax1, ay1, ax2, ay2;
338  ax1 = refSegment.A.x;
339  ay1 = refSegment.A.y;
340  ax2 = refSegment.B.x;
341  ay2 = refSegment.B.y;
342 
343  int bx1, by1, bx2, by2;
344  bx1 = testSegment.A.x;
345  by1 = testSegment.A.y;
346  bx2 = testSegment.B.x;
347  by2 = testSegment.B.y;
348 
349  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
350  0,
351  ax1, ay1, ax2, ay2,
352  0,
353  zone2zoneClearance,
354  &pt.x, &pt.y );
355 
356  if( d < zone2zoneClearance )
357  conflictPoints.insert( pt );
358  }
359  }
360 
361  for( wxPoint pt : conflictPoints )
362  {
363  if( aCreateMarkers )
364  commit.Add( m_markerFactory.NewMarker(
365  pt, zoneRef, zoneToTest, DRCE_ZONES_TOO_CLOSE ) );
366 
367  nerrors++;
368  }
369  }
370  }
371 
372  if( aCreateMarkers )
373  commit.Push( wxEmptyString, false, false );
374 
375  return nerrors;
376 }
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:185
#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:775
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:981
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:239
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:651
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:96
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
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:952
BOARD * GetBoard() const
DRC_MARKER_FACTORY m_markerFactory
Class that generates markers.
Definition: drc.h:243
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:191
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 586 of file drc.cpp.

587 {
588  // update my pointers, m_pcbEditorFrame is the only unchangeable one
590 
591  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
592  {
599 
601  }
602 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:242
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:722
DRC_LIST m_footprints
list of footprint warnings, as DRC_ITEMs
Definition: drc.h:246
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc.h:240
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:289
Class DRC_LIST_GENERIC is an implementation of the interface named DRC_ITEM_LIST which uses a vector ...
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:239
DRCLISTBOX * m_FootprintsListBox
BOARD * GetBoard() const
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:245

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

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

Friends And Related Function Documentation

◆ DIALOG_DRC_CONTROL

friend class DIALOG_DRC_CONTROL
friend

Definition at line 190 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 241 of file drc.h.

Referenced by doTrackDrc(), and testOutline().

◆ m_currentMarker

◆ m_doCreateRptFile

bool DRC::m_doCreateRptFile
private

Definition at line 199 of file drc.h.

Referenced by DestroyDRCDialog(), DRC(), DIALOG_DRC_CONTROL::OnStartdrcClick(), and ShowDRCDialog().

◆ m_doKeepoutTest

bool DRC::m_doKeepoutTest
private

Definition at line 198 of file drc.h.

Referenced by DRC(), and RunTests().

◆ m_doPad2PadTest

bool DRC::m_doPad2PadTest
private

Definition at line 195 of file drc.h.

Referenced by DRC(), and RunTests().

◆ m_doUnconnectedTest

bool DRC::m_doUnconnectedTest
private

Definition at line 196 of file drc.h.

Referenced by DRC(), and RunTests().

◆ m_doZonesTest

bool DRC::m_doZonesTest
private

Definition at line 197 of file drc.h.

Referenced by DRC(), DIALOG_DRC_CONTROL::OnStartdrcClick(), and testTracks().

◆ m_drcDialog

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 242 of file drc.h.

Referenced by DestroyDRCDialog(), DRC(), RunTests(), 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 214 of file drc.h.

Referenced by addMarkerToPcb(), doTrackDrc(), DRC(), DrcOnCreatingTrack(), DrcOnCreatingZone(), and DIALOG_DRC_CONTROL::OnStartdrcClick().

◆ m_drcRun

bool DRC::m_drcRun
private

Definition at line 247 of file drc.h.

Referenced by DRC(), RunTests(), and DIALOG_DRC_CONTROL::UpdateDisplayedCounts().

◆ m_footprints

DRC_LIST DRC::m_footprints
private

list of footprint warnings, as DRC_ITEMs

Definition at line 246 of file drc.h.

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

◆ m_footprintsTested

bool DRC::m_footprintsTested
private

Definition at line 248 of file drc.h.

Referenced by DRC(), RunTests(), and DIALOG_DRC_CONTROL::UpdateDisplayedCounts().

◆ m_markerFactory

◆ m_padToTestPos

wxPoint DRC::m_padToTestPos
private

Definition at line 220 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 200 of file drc.h.

Referenced by DRC(), DIALOG_DRC_CONTROL::OnStartdrcClick(), and RunTests().

◆ m_reportAllTrackErrors

bool DRC::m_reportAllTrackErrors
private

◆ m_rptFilename

wxString DRC::m_rptFilename
private

Definition at line 204 of file drc.h.

Referenced by DestroyDRCDialog(), DIALOG_DRC_CONTROL::OnStartdrcClick(), and ShowDRCDialog().

◆ m_segmAngle

double DRC::m_segmAngle
private

Definition at line 228 of file drc.h.

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

◆ m_segmEnd

wxPoint DRC::m_segmEnd
private

Definition at line 221 of file drc.h.

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

◆ m_segmLength

int DRC::m_segmLength
private

Definition at line 229 of file drc.h.

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

◆ m_testFootprints

bool DRC::m_testFootprints
private

Definition at line 202 of file drc.h.

Referenced by DRC(), DIALOG_DRC_CONTROL::OnStartdrcClick(), and RunTests().

◆ m_unconnected

DRC_LIST DRC::m_unconnected
private

list of unconnected pads, as DRC_ITEMs

Definition at line 245 of file drc.h.

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

◆ m_xcliphi

int DRC::m_xcliphi
private

Definition at line 236 of file drc.h.

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

◆ m_xcliplo

int DRC::m_xcliplo
private

Definition at line 234 of file drc.h.

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

◆ m_ycliphi

int DRC::m_ycliphi
private

Definition at line 237 of file drc.h.

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

◆ m_ycliplo

int DRC::m_ycliplo
private

Definition at line 235 of file drc.h.

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


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