KiCad PCB EDA Suite
DRC Class Reference

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

#include <drc.h>

Public Member Functions

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

Private Member Functions

void updatePointers ()
 Update needed pointers from the one pointer which is known not to change. More...
 
MARKER_PCBnewMarker (TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
 Function newMarker Creates a marker on a track, via or pad. More...
 
MARKER_PCBnewMarker (TRACK *aTrack, ZONE_CONTAINER *aConflictZone, int aErrorCode)
 
MARKER_PCBnewMarker (D_PAD *aPad, BOARD_ITEM *aConflictItem, int aErrorCode)
 
MARKER_PCBnewMarker (const wxPoint &aPos, BOARD_ITEM *aItem, int aErrorCode)
 Function newMarker Creates a marker at a given location. More...
 
MARKER_PCBnewMarker (const wxPoint &aPos, BOARD_ITEM *aItem, BOARD_ITEM *bItem, int aErrorCode)
 
MARKER_PCBnewMarker (int aErrorCode, const wxString &aMessage)
 Create a MARKER which will report on a generic problem with the board which is not geographically locatable. More...
 
void addMarkerToPcb (MARKER_PCB *aMarker)
 Adds a DRC marker to the PCB through the COMMIT mechanism. More...
 
bool testNetClasses ()
 Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings. More...
 
void testTracks (wxWindow *aActiveWindow, bool aShowProgressBar)
 Perform the DRC on all tracks. More...
 
void testPad2Pad ()
 
void testDrilledHoles ()
 
void testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testCopperTextItem (BOARD_ITEM *aTextItem)
 
void testCopperDrawItem (DRAWSEGMENT *aDrawing)
 
void testCopperTextAndGraphics ()
 
void testDisabledLayers ()
 

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

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

Static Private Member Functions

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

Private Attributes

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

Friends

class DIALOG_DRC_CONTROL
 

Detailed Description

Design Rule Checker object that performs all the DRC tests.

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

Definition at line 174 of file drc.h.

Constructor & Destructor Documentation

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 131 of file drc.cpp.

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

132 {
133  m_pcbEditorFrame = aPcbWindow;
134  m_pcb = aPcbWindow->GetBoard();
135  m_drcDialog = NULL;
136 
137  // establish initial values for everything:
138  m_drcInLegacyRoutingMode = false;
139  m_doPad2PadTest = true; // enable pad to pad clearance tests
140  m_doUnconnectedTest = true; // enable unconnected tests
141  m_doZonesTest = true; // enable zone to items clearance tests
142  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
143  m_refillZones = false; // Only fill zones if requested by user.
144  m_reportAllTrackErrors = false;
145  m_doCreateRptFile = false;
146 
147  // m_rptFilename set to empty by its constructor
148 
149  m_currentMarker = NULL;
150 
151  m_segmAngle = 0;
152  m_segmLength = 0;
153 
154  m_xcliplo = 0;
155  m_ycliplo = 0;
156  m_xcliphi = 0;
157  m_ycliphi = 0;
158 }
bool m_refillZones
Definition: drc.h:186
bool m_doCreateRptFile
Definition: drc.h:185
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:227
int m_ycliplo
Definition: drc.h:220
int m_ycliphi
Definition: drc.h:222
int m_segmLength
Definition: drc.h:214
BOARD * GetBoard() const
BOARD * m_pcb
Definition: drc.h:225
bool m_doKeepoutTest
Definition: drc.h:184
bool m_doZonesTest
Definition: drc.h:183
bool m_reportAllTrackErrors
Definition: drc.h:187
int m_xcliphi
Definition: drc.h:221
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
bool m_doPad2PadTest
Definition: drc.h:181
MARKER_PCB * m_currentMarker
Definition: drc.h:191
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:199
int m_xcliplo
Definition: drc.h:219
bool m_doUnconnectedTest
Definition: drc.h:182
double m_segmAngle
Definition: drc.h:213
DRC::~DRC ( )

Definition at line 161 of file drc.cpp.

References i, and m_unconnected.

162 {
163  // maybe someday look at pointainer.h <- google for "pointainer.h"
164  for( unsigned i = 0; i<m_unconnected.size(); ++i )
165  delete m_unconnected[i];
166 }
size_t i
Definition: json11.cpp:597
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:229

Member Function Documentation

void DRC::addMarkerToPcb ( MARKER_PCB aMarker)
private

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

Definition at line 100 of file drc.cpp.

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().

101 {
102  // In legacy routing mode, do not add markers to the board.
103  // only shows the drc error message
105  {
106  m_pcbEditorFrame->SetMsgPanel( aMarker );
107  delete aMarker;
108  m_currentMarker = nullptr;
109  }
110  else
111  {
112  BOARD_COMMIT commit( m_pcbEditorFrame );
113  commit.Add( aMarker );
114  commit.Push( wxEmptyString, false, false );
115  }
116 }
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:224
MARKER_PCB * m_currentMarker
Definition: drc.h:191
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:199
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 840 of file drc_clearance_test_functions.cpp.

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

Referenced by doPadToPadsDrc().

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

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

Referenced by checkClearancePadToPad(), and doTrackDrc().

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

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

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1425 {
1426 #define WHEN_OUTSIDE return true
1427 #define WHEN_INSIDE
1428  int temp;
1429 
1430  if( aSegStart.x > aSegEnd.x )
1431  std::swap( aSegStart, aSegEnd );
1432 
1433  if( (aSegEnd.x <= m_xcliplo) || (aSegStart.x >= m_xcliphi) )
1434  {
1435  WHEN_OUTSIDE;
1436  }
1437 
1438  if( aSegStart.y < aSegEnd.y )
1439  {
1440  if( (aSegEnd.y <= m_ycliplo) || (aSegStart.y >= m_ycliphi) )
1441  {
1442  WHEN_OUTSIDE;
1443  }
1444 
1445  if( aSegStart.y < m_ycliplo )
1446  {
1447  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1448  (aSegEnd.y - aSegStart.y) );
1449 
1450  if( (aSegStart.x += temp) >= m_xcliphi )
1451  {
1452  WHEN_OUTSIDE;
1453  }
1454 
1455  aSegStart.y = m_ycliplo;
1456  WHEN_INSIDE;
1457  }
1458 
1459  if( aSegEnd.y > m_ycliphi )
1460  {
1461  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1462  (aSegEnd.y - aSegStart.y) );
1463 
1464  if( (aSegEnd.x -= temp) <= m_xcliplo )
1465  {
1466  WHEN_OUTSIDE;
1467  }
1468 
1469  aSegEnd.y = m_ycliphi;
1470  WHEN_INSIDE;
1471  }
1472 
1473  if( aSegStart.x < m_xcliplo )
1474  {
1475  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1476  (aSegEnd.x - aSegStart.x) );
1477  aSegStart.y += temp;
1478  aSegStart.x = m_xcliplo;
1479  WHEN_INSIDE;
1480  }
1481 
1482  if( aSegEnd.x > m_xcliphi )
1483  {
1484  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1485  (aSegEnd.x - aSegStart.x) );
1486  aSegEnd.y -= temp;
1487  aSegEnd.x = m_xcliphi;
1488  WHEN_INSIDE;
1489  }
1490  }
1491  else
1492  {
1493  if( (aSegStart.y <= m_ycliplo) || (aSegEnd.y >= m_ycliphi) )
1494  {
1495  WHEN_OUTSIDE;
1496  }
1497 
1498  if( aSegStart.y > m_ycliphi )
1499  {
1500  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1501  (aSegStart.y - aSegEnd.y) );
1502 
1503  if( (aSegStart.x += temp) >= m_xcliphi )
1504  {
1505  WHEN_OUTSIDE;
1506  }
1507 
1508  aSegStart.y = m_ycliphi;
1509  WHEN_INSIDE;
1510  }
1511 
1512  if( aSegEnd.y < m_ycliplo )
1513  {
1514  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1515  (aSegStart.y - aSegEnd.y) );
1516 
1517  if( (aSegEnd.x -= temp) <= m_xcliplo )
1518  {
1519  WHEN_OUTSIDE;
1520  }
1521 
1522  aSegEnd.y = m_ycliplo;
1523  WHEN_INSIDE;
1524  }
1525 
1526  if( aSegStart.x < m_xcliplo )
1527  {
1528  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1529  (aSegEnd.x - aSegStart.x) );
1530  aSegStart.y -= temp;
1531  aSegStart.x = m_xcliplo;
1532  WHEN_INSIDE;
1533  }
1534 
1535  if( aSegEnd.x > m_xcliphi )
1536  {
1537  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1538  (aSegEnd.x - aSegStart.x) );
1539  aSegEnd.y += temp;
1540  aSegEnd.x = m_xcliphi;
1541  WHEN_INSIDE;
1542  }
1543  }
1544 
1545  // Do not divide here to avoid rounding errors
1546  if( ( (aSegEnd.x + aSegStart.x) < m_xcliphi * 2 )
1547  && ( (aSegEnd.x + aSegStart.x) > m_xcliplo * 2) \
1548  && ( (aSegEnd.y + aSegStart.y) < m_ycliphi * 2 )
1549  && ( (aSegEnd.y + aSegStart.y) > m_ycliplo * 2 ) )
1550  {
1551  return false;
1552  }
1553  else
1554  {
1555  return true;
1556  }
1557 }
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
int m_ycliplo
Definition: drc.h:220
int m_ycliphi
Definition: drc.h:222
int m_xcliphi
Definition: drc.h:221
#define WHEN_INSIDE
int m_xcliplo
Definition: drc.h:219
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 1371 of file drc_clearance_test_functions.cpp.

References abs, and EuclideanNorm().

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1372 {
1373  if( abs( aCentre.y ) >= aRadius ) // trivial case
1374  return true;
1375 
1376  // Here, distance between aCentre and X axis is < aRadius
1377  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1378  {
1379  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1380  return false; // aCentre is between the starting point and the ending point of the segm
1381 
1382  if( aCentre.x > aLength ) // aCentre is after the ending point
1383  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1384 
1385  if( EuclideanNorm( aCentre ) < aRadius )
1386  // distance between aCentre and the starting point or the ending point is < aRadius
1387  return false;
1388  }
1389 
1390  return true;
1391 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
#define abs(a)
Definition: auxiliary.h:84
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 119 of file drc.cpp.

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().

120 {
121  if( m_drcDialog )
122  {
124 
125  m_drcDialog->Destroy();
126  m_drcDialog = NULL;
127  }
128 }
bool m_doCreateRptFile
Definition: drc.h:185
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:227
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:184
wxString m_rptFilename
Definition: drc.h:189
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 743 of file drc_clearance_test_functions.cpp.

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_pcb, SHAPE_POLY_SET::VERTEX_INDEX::m_polygon, SHAPE_POLY_SET::VERTEX_INDEX::m_vertex, max, newMarker(), ZONE_CONTAINER::Outline(), SHAPE_POLY_SET::Polygon(), SHAPE_LINE_CHAIN::Segment(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by DrcOnCreatingZone().

744 {
745  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
746  return true;
747  // Get polygon, contour and vertex index.
749 
750  // If the vertex does not exist, there is no conflict
751  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
752  return true;
753 
754  // Retrieve the selected contour
755  SHAPE_LINE_CHAIN contour;
756  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
757 
758  // Retrieve the segment that starts at aCornerIndex-th corner.
759  SEG selectedSegment = contour.Segment( index.m_vertex );
760 
761  VECTOR2I start = selectedSegment.A;
762  VECTOR2I end = selectedSegment.B;
763 
764  // iterate through all areas
765  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
766  {
767  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
768  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
769  aArea->GetZoneClearance() );
770 
771  // test for same layer
772  if( area_to_test->GetLayer() != aArea->GetLayer() )
773  continue;
774 
775  // Test for same net
776  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
777  continue;
778 
779  // test for same priority
780  if( area_to_test->GetPriority() != aArea->GetPriority() )
781  continue;
782 
783  // test for same type
784  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
785  continue;
786 
787  // For keepout, there is no clearance, so use a minimal value for it
788  // use 1, not 0 as value to avoid some issues in tests
789  if( area_to_test->GetIsKeepout() )
790  zone_clearance = 1;
791 
792  // test for ending line inside area_to_test
793  if( area_to_test->Outline()->Contains( end ) )
794  {
795  wxPoint pos( end.x, end.y );
796  m_currentMarker = newMarker( pos, aArea, area_to_test, DRCE_ZONES_INTERSECT );
797  return false;
798  }
799 
800  // now test spacing between areas
801  int ax1 = start.x;
802  int ay1 = start.y;
803  int ax2 = end.x;
804  int ay2 = end.y;
805 
806  // Iterate through all edges in the polygon.
808  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
809  {
810  SEG segment = *iterator;
811 
812  int bx1 = segment.A.x;
813  int by1 = segment.A.y;
814  int bx2 = segment.B.x;
815  int by2 = segment.B.y;
816 
817  int x, y; // variables containing the intersecting point coordinates
818  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
819  0,
820  ax1, ay1, ax2, ay2,
821  0,
822  zone_clearance,
823  &x, &y );
824 
825  if( d < zone_clearance )
826  {
827  // COPPERAREA_COPPERAREA error : edge intersect or too close
828  m_currentMarker = newMarker( wxPoint( x, y ), aArea, area_to_test,
830  return false;
831  }
832 
833  }
834  }
835 
836  return true;
837 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:175
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:241
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, bool aIgnoreHoles=false) const
Returns true if a given subpolygon contains the point aP.
Struct VERTEX_INDEX.
Class SEGMENT_ITERATOR_TEMPLATE.
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)
#define DRCE_ZONES_INTERSECT
copper area outlines intersect
Definition: drc.h:67
BOARD * m_pcb
Definition: drc.h:225
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:628
bool GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Function GetRelativeIndices.
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc.h:191
Definition: seg.h:36
SEG Segment(int aIndex)
Function Segment()
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:181
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
#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:68
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:106
int GetZoneClearance() const
Definition: class_zone.h:197
VECTOR2I B
Definition: seg.h:45
bool DRC::doFootprintOverlappingDrc ( )
private

Test for footprint courtyard overlaps.

Returns
bool - false if DRC error or true if OK

Definition at line 1405 of file drc.cpp.

References addMarkerToPcb(), SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::BooleanIntersection(), DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT, DRCE_MISSING_COURTYARD_IN_FOOTPRINT, DRCE_OVERLAPPING_FOOTPRINTS, BOARD::GetDesignSettings(), BOARD::m_Modules, m_pcb, BOARD_DESIGN_SETTINGS::m_ProhibitOverlappingCourtyards, BOARD_DESIGN_SETTINGS::m_RequireCourtyards, newMarker(), MODULE::Next(), SHAPE_POLY_SET::OutlineCount(), SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::RemoveAllContours(), SHAPE_POLY_SET::Vertex(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by RunTests().

1406 {
1407  // Detects missing (or malformed) footprint courtyard,
1408  // and for footprint with courtyard, courtyards overlap.
1409  wxString msg;
1410  bool success = true;
1411 
1412  // Update courtyard polygons, and test for missing courtyard definition:
1413  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1414  {
1415  wxPoint pos = footprint->GetPosition();
1416  bool is_ok = footprint->BuildPolyCourtyard();
1417 
1419  {
1421  success = false;
1422  }
1423 
1425  continue;
1426 
1427  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 &&
1428  footprint->GetPolyCourtyardBack().OutlineCount() == 0 &&
1429  is_ok )
1430  {
1432  success = false;
1433  }
1434  }
1435 
1437  return success;
1438 
1439  // Now test for overlapping on top layer:
1440  SHAPE_POLY_SET courtyard; // temporary storage of the courtyard of current footprint
1441 
1442  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1443  {
1444  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 )
1445  continue; // No courtyard defined
1446 
1447  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1448  {
1449  if( candidate->GetPolyCourtyardFront().OutlineCount() == 0 )
1450  continue; // No courtyard defined
1451 
1452  courtyard.RemoveAllContours();
1453  courtyard.Append( footprint->GetPolyCourtyardFront() );
1454 
1455  // Build the common area between footprint and the candidate:
1456  courtyard.BooleanIntersection( candidate->GetPolyCourtyardFront(),
1458 
1459  // If no overlap, courtyard is empty (no common area).
1460  // Therefore if a common polygon exists, this is a DRC error
1461  if( courtyard.OutlineCount() )
1462  {
1463  //Overlap between footprint and candidate
1464  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1465  addMarkerToPcb( newMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
1467  success = false;
1468  }
1469  }
1470  }
1471 
1472  // Test for overlapping on bottom layer:
1473  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1474  {
1475  if( footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
1476  continue; // No courtyard defined
1477 
1478  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1479  {
1480  if( candidate->GetPolyCourtyardBack().OutlineCount() == 0 )
1481  continue; // No courtyard defined
1482 
1483  courtyard.RemoveAllContours();
1484  courtyard.Append( footprint->GetPolyCourtyardBack() );
1485 
1486  // Build the common area between footprint and the candidate:
1487  courtyard.BooleanIntersection( candidate->GetPolyCourtyardBack(),
1489 
1490  // If no overlap, courtyard is empty (no common area).
1491  // Therefore if a common polygon exists, this is a DRC error
1492  if( courtyard.OutlineCount() )
1493  {
1494  //Overlap between footprint and candidate
1495  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1496  addMarkerToPcb( newMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
1498  success = false;
1499  }
1500  }
1501  }
1502 
1503  return success;
1504 }
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
MODULE * Next() const
Definition: class_module.h:122
int OutlineCount() const
Returns the number of outlines in the set
#define DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT
footprint has a courtyard but malformed
Definition: drc.h:92
#define DRCE_MISSING_COURTYARD_IN_FOOTPRINT
footprint has no courtyard defined
Definition: drc.h:91
BOARD * m_pcb
Definition: drc.h:225
VECTOR2I & Vertex(int aIndex, int aOutline, int aHole)
Returns the index-th vertex in a given hole outline within a given outline
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
Class SHAPE_POLY_SET.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
#define DRCE_OVERLAPPING_FOOTPRINTS
footprint courtyards overlap
Definition: drc.h:90
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp ...
bool m_RequireCourtyards
require courtyard definitions in footprints
DLIST< MODULE > m_Modules
Definition: class_board.h:249
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
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) ...
bool DRC::doNetClass ( const std::shared_ptr< NETCLASS > &  aNetClass,
wxString &  msg 
)
private

Definition at line 570 of file drc.cpp.

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, 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 newMarker().

Referenced by testNetClasses().

571 {
572  bool ret = true;
573 
575 
576 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
577 
578 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
579  if( nc->GetClearance() < g.m_MinClearance )
580  {
581  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
582  GetChars( nc->GetName() ),
583  FmtVal( nc->GetClearance() ),
584  FmtVal( g.m_TrackClearance )
585  );
586 
588  m_currentMarker = nullptr;
589  ret = false;
590  }
591 #endif
592 
593  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
594  {
595  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
596  GetChars( nc->GetName() ),
597  FmtVal( nc->GetTrackWidth() ),
599  );
600 
602  ret = false;
603  }
604 
605  if( nc->GetViaDiameter() < g.m_ViasMinSize )
606  {
607  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
608  GetChars( nc->GetName() ),
609  FmtVal( nc->GetViaDiameter() ),
610  FmtVal( g.m_ViasMinSize )
611  );
612 
614  ret = false;
615  }
616 
617  if( nc->GetViaDrill() < g.m_ViasMinDrill )
618  {
619  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
620  GetChars( nc->GetName() ),
621  FmtVal( nc->GetViaDrill() ),
623  );
624 
626  ret = false;
627  }
628 
629  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
630  {
631  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
632  GetChars( nc->GetName() ),
633  FmtVal( nc->GetuViaDiameter() ),
634  FmtVal( g.m_MicroViasMinSize ) );
635 
637  ret = false;
638  }
639 
640  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
641  {
642  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
643  GetChars( nc->GetName() ),
644  FmtVal( nc->GetuViaDrill() ),
646 
648  ret = false;
649  }
650 
651  return ret;
652 }
#define DRCE_NETCLASS_TRACKWIDTH
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc.h:77
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:78
BOARD * m_pcb
Definition: drc.h:225
#define DRCE_NETCLASS_uVIADRILLSIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc.h:82
#define DRCE_NETCLASS_VIASIZE
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc.h:79
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
int m_TrackMinWidth
track min value for width ((min copper size value
int m_ViasMinSize
vias (not micro vias) min diameter
int m_ViasMinDrill
vias (not micro vias) min drill diameter
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:80
int m_MicroViasMinSize
micro vias (not vias) min diameter
#define FmtVal(x)
MARKER_PCB * m_currentMarker
Definition: drc.h:191
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
#define DRCE_NETCLASS_uVIASIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc.h:81
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
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 1273 of file drc.cpp.

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_pcb, 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().

1274 {
1275  const static LSET all_cu = LSET::AllCuMask();
1276 
1277  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1278 
1279  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1280  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1281  * Therefore, this dummy pad is a circle or an oval.
1282  * A pad must have a parent because some functions expect a non null parent
1283  * to find the parent board, and some other data
1284  */
1285  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1286  D_PAD dummypad( &dummymodule );
1287 
1288  // Ensure the hole is on all copper layers
1289  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1290 
1291  // Use the minimal local clearance value for the dummy pad.
1292  // The clearance of the active pad will be used as minimum distance to a hole
1293  // (a value = 0 means use netclass value)
1294  dummypad.SetLocalClearance( 1 );
1295 
1296  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1297  {
1298  D_PAD* pad = *pad_list;
1299 
1300  if( pad == aRefPad )
1301  continue;
1302 
1303  // We can stop the test when pad->GetPosition().x > x_limit
1304  // because the list is sorted by X values
1305  if( pad->GetPosition().x > x_limit )
1306  break;
1307 
1308  // No problem if pads which are on copper layers are on different copper layers,
1309  // (pads can be only on a technical layer, to build complex pads)
1310  // but their hole (if any ) can create DRC error because they are on all
1311  // copper layers, so we test them
1312  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1313  ( pad->GetLayerSet() & all_cu ) != 0 &&
1314  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1315  {
1316  // if holes are in the same location and have the same size and shape,
1317  // this can be accepted
1318  if( pad->GetPosition() == aRefPad->GetPosition()
1319  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1320  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1321  {
1322  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1323  continue;
1324 
1325  // for oval holes: must also have the same orientation
1326  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1327  continue;
1328  }
1329 
1330  /* Here, we must test clearance between holes and pads
1331  * dummy pad size and shape is adjusted to pad drill size and shape
1332  */
1333  if( pad->GetDrillSize().x )
1334  {
1335  // pad under testing has a hole, test this hole against pad reference
1336  dummypad.SetPosition( pad->GetPosition() );
1337  dummypad.SetSize( pad->GetDrillSize() );
1338  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1340  dummypad.SetOrientation( pad->GetOrientation() );
1341 
1342  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1343  {
1344  // here we have a drc error on pad!
1345  m_currentMarker = newMarker( pad, aRefPad, DRCE_HOLE_NEAR_PAD );
1346  return false;
1347  }
1348  }
1349 
1350  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1351  {
1352  dummypad.SetPosition( aRefPad->GetPosition() );
1353  dummypad.SetSize( aRefPad->GetDrillSize() );
1354  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1356  dummypad.SetOrientation( aRefPad->GetOrientation() );
1357 
1358  if( !checkClearancePadToPad( pad, &dummypad ) )
1359  {
1360  // here we have a drc error on aRefPad!
1361  m_currentMarker = newMarker( aRefPad, pad, DRCE_HOLE_NEAR_PAD );
1362  return false;
1363  }
1364  }
1365 
1366  continue;
1367  }
1368 
1369  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1370  // But no problem if pads have the same netcode (same net)
1371  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1372  continue;
1373 
1374  // if pads are from the same footprint
1375  if( pad->GetParent() == aRefPad->GetParent() )
1376  {
1377  // and have the same pad number ( equivalent pads )
1378 
1379  // one can argue that this 2nd test is not necessary, that any
1380  // two pads from a single module are acceptable. This 2nd test
1381  // should eventually be a configuration option.
1382  if( pad->PadNameEqual( aRefPad ) )
1383  continue;
1384  }
1385 
1386  // if either pad has no drill and is only on technical layers, not a clearance violation
1387  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1388  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1389  {
1390  continue;
1391  }
1392 
1393  if( !checkClearancePadToPad( aRefPad, pad ) )
1394  {
1395  // here we have a drc error!
1396  m_currentMarker = newMarker( aRefPad, pad, DRCE_PAD_NEAR_PAD1 );
1397  return false;
1398  }
1399  }
1400 
1401  return true;
1402 }
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
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:207
#define DRCE_PAD_NEAR_PAD1
pad too close to pad
Definition: drc.h:64
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc.h:70
MODULE * GetParent() const
Definition: class_pad.h:162
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:388
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
BOARD * m_pcb
Definition: drc.h:225
Class LSET is a set of PCB_LAYER_IDs.
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:402
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
int GetNetCode() const
Function GetNetCode.
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:191
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:382
const wxPoint GetPosition() const override
Definition: class_pad.h:220
bool DRC::doTrackDrc ( TRACK aRefSeg,
TRACK aStart,
bool  doPads = true 
)
private

Test the current segment.

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

Definition at line 138 of file drc_clearance_test_functions.cpp.

References abs, COMMIT::Add(), addMarkerToPcb(), LSET::AllCuMask(), PNS::angle(), ArcTangente(), B_Cu, checkClearanceSegmToPad(), checkLine(), checkMarginToCircle(), delta, SHAPE_POLY_SET::Distance(), DRCE_BURIED_VIA_NOT_ALLOWED, DRCE_ENDS_PROBLEM1, DRCE_ENDS_PROBLEM2, DRCE_ENDS_PROBLEM3, DRCE_ENDS_PROBLEM4, DRCE_ENDS_PROBLEM5, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR, DRCE_MICRO_VIA_NOT_ALLOWED, DRCE_TOO_SMALL_MICROVIA, DRCE_TOO_SMALL_MICROVIA_DRILL, DRCE_TOO_SMALL_TRACK_WIDTH, DRCE_TOO_SMALL_VIA, DRCE_TOO_SMALL_VIA_DRILL, DRCE_TRACK_ENDS1, DRCE_TRACK_ENDS2, DRCE_TRACK_ENDS3, DRCE_TRACK_ENDS4, DRCE_TRACK_NEAR_EDGE, DRCE_TRACK_NEAR_PAD, DRCE_TRACK_NEAR_THROUGH_HOLE, DRCE_TRACK_NEAR_VIA, DRCE_TRACK_NEAR_ZONE, DRCE_TRACK_SEGMENTS_TOO_CLOSE, DRCE_TRACKS_CROSSING, DRCE_VIA_HOLE_BIGGER, DRCE_VIA_NEAR_TRACK, DRCE_VIA_NEAR_VIA, err, EuclideanNorm(), F_Cu, TRACK::GetClearance(), BOARD_DESIGN_SETTINGS::GetCopperLayerCount(), BOARD::GetDesignSettings(), D_PAD::GetDrillShape(), D_PAD::GetDrillSize(), VIA::GetDrillValue(), TRACK::GetEnd(), BOARD_ITEM::GetLayerSet(), D_PAD::GetLayerSet(), BOARD_CONNECTED_ITEM::GetNetClass(), BOARD_CONNECTED_ITEM::GetNetCode(), D_PAD::GetOrientation(), BOARD::GetPadCount(), BOARD::GetPads(), TRACK::GetPosition(), D_PAD::GetPosition(), VIA::GetPosition(), TRACK::GetStart(), VIA::GetViaType(), TRACK::GetWidth(), In1_Cu, SHAPE_POLY_SET::IterateSegmentsWithHoles(), VIA::LayerPair(), BOARD_DESIGN_SETTINGS::m_BlindBuriedViaAllowed, m_board_outlines, m_drcInLegacyRoutingMode, 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, 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().

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

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_pcb, newMarker(), ZONE_CONTAINER::Outline(), PCB_TRACE_T, PCB_VIA_T, and EDA_ITEM::Type().

Referenced by DrcOnCreatingTrack().

1227 {
1228  // Test keepout areas for vias, tracks and pads inside keepout areas
1229  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
1230  {
1231  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
1232 
1233  if( !area->GetIsKeepout() )
1234  continue;
1235 
1236  if( aRefSeg->Type() == PCB_TRACE_T )
1237  {
1238  if( !area->GetDoNotAllowTracks() )
1239  continue;
1240 
1241  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
1242  continue;
1243 
1244  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
1245  aRefSeg->GetWidth() ) == 0 )
1246  {
1248  return false;
1249  }
1250  }
1251  else if( aRefSeg->Type() == PCB_VIA_T )
1252  {
1253  if( !area->GetDoNotAllowVias() )
1254  continue;
1255 
1256  auto viaLayers = aRefSeg->GetLayerSet();
1257 
1258  if( !area->CommonLayerExists( viaLayers ) )
1259  continue;
1260 
1261  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1262  {
1264  return false;
1265  }
1266  }
1267  }
1268 
1269  return true;
1270 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set...
Definition: class_zone.cpp:194
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_zone.cpp:265
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:241
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:83
const wxPoint & GetEnd() const
Definition: class_track.h:123
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:225
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:628
const wxPoint GetPosition() const override
Definition: class_track.h:117
const wxPoint & GetStart() const
Definition: class_track.h:126
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
MARKER_PCB * m_currentMarker
Definition: drc.h:191
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:631
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
bool GetDoNotAllowVias() const
Definition: class_zone.h:630
int GetWidth() const
Definition: class_track.h:120
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc.h:84
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
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 169 of file drc.cpp.

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().

170 {
171  updatePointers();
172 
173  // Set right options for this on line drc
174  int drc_state = m_drcInLegacyRoutingMode;
176  int rpt_state = m_reportAllTrackErrors;
177  m_reportAllTrackErrors = false;
178 
179  if( !doTrackDrc( aRefSegm, aList, true ) )
180  {
181  if( m_currentMarker )
182  {
184  delete m_currentMarker;
185  m_currentMarker = nullptr;
186  }
187 
188  m_drcInLegacyRoutingMode = drc_state;
189  m_reportAllTrackErrors = rpt_state;
190  return BAD_DRC;
191  }
192 
193  if( !doTrackKeepoutDrc( aRefSegm ) )
194  {
195  if( m_currentMarker )
196  {
198  delete m_currentMarker;
199  m_currentMarker = nullptr;
200  }
201 
202  m_drcInLegacyRoutingMode = drc_state;
203  m_reportAllTrackErrors = rpt_state;
204  return BAD_DRC;
205  }
206 
207  m_drcInLegacyRoutingMode = drc_state;
208  m_reportAllTrackErrors = rpt_state;
209  return OK_DRC;
210 }
#define OK_DRC
Definition: drc.h:37
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:1226
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:553
bool m_reportAllTrackErrors
Definition: drc.h:187
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
#define BAD_DRC
Definition: drc.h:38
MARKER_PCB * m_currentMarker
Definition: drc.h:191
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:199
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 363 of file drc.cpp.

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().

364 {
365  updatePointers();
366 
367  // Set right options for this on line drc
368  int drc_state = m_drcInLegacyRoutingMode;
370  int rpt_state = m_reportAllTrackErrors;
371  m_reportAllTrackErrors = false;
372 
373  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
374  {
375  wxASSERT( m_currentMarker );
377  delete m_currentMarker;
378  m_currentMarker = nullptr;
379  m_drcInLegacyRoutingMode = drc_state;
380  m_reportAllTrackErrors = rpt_state;
381  return BAD_DRC;
382  }
383 
384  m_drcInLegacyRoutingMode = drc_state;
385  m_reportAllTrackErrors = rpt_state;
386  return OK_DRC;
387 }
#define OK_DRC
Definition: drc.h:37
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:553
bool m_reportAllTrackErrors
Definition: drc.h:187
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
#define BAD_DRC
Definition: drc.h:38
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:191
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:199
MARKER_PCB* DRC::GetCurrentMarker ( )
inline
Returns
a pointer to the current marker (last created marker

Definition at line 550 of file drc.h.

Referenced by PCB_EDIT_FRAME::Other_Layer_Route().

551  {
552  return m_currentMarker;
553  }
MARKER_PCB * m_currentMarker
Definition: drc.h:191
void DRC::ListUnconnectedPads ( )

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

Definition at line 544 of file drc.cpp.

References testUnconnected(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick().

545 {
546  testUnconnected();
547 
548  // update the m_drcDialog listboxes
549  updatePointers();
550 }
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:553
void testUnconnected()
Definition: drc.cpp:854
MARKER_PCB * DRC::newMarker ( TRACK aTrack,
BOARD_ITEM aConflitItem,
const SEG aConflictSeg,
int  aErrorCode 
)
private

Function newMarker Creates a marker on a track, via or pad.

Parameters
aTrack/aPadThe reference item.
aConflitItemAnother item on the board which is in conflict with the reference item.
aErrorCodeAn ID for the particular type of error that is being reported.

Definition at line 93 of file drc_marker_functions.cpp.

References SEG::Distance(), EPSILON, TRACK::GetEnd(), GetLineLength(), BOARD_ITEM::GetPosition(), TRACK::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), and m_pcbEditorFrame.

Referenced by doEdgeZoneDrc(), doFootprintOverlappingDrc(), doNetClass(), doPadToPadsDrc(), doTrackDrc(), doTrackKeepoutDrc(), testCopperDrawItem(), testCopperTextItem(), testDisabledLayers(), testKeepoutAreas(), testOutline(), testZones(), and TestZoneToZoneOutline().

95 {
96  wxPoint markerPos;
97  wxPoint pt1 = aTrack->GetPosition();
98  wxPoint pt2 = aTrack->GetEnd();
99 
100  // Do a binary search along the track for a "good enough" marker location
101  while( GetLineLength( pt1, pt2 ) > EPSILON )
102  {
103  if( aConflictSeg.Distance( pt1 ) < aConflictSeg.Distance( pt2 ) )
104  pt2 = ( pt1 + pt2 ) / 2;
105  else
106  pt1 = ( pt1 + pt2 ) / 2;
107  }
108 
109  // Once we're within EPSILON pt1 and pt2 are "equivalent"
110  markerPos = pt1;
111 
112  return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, markerPos,
113  aTrack, aTrack->GetPosition(),
114  aConflitItem, aConflitItem->GetPosition() );
115 }
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
const wxPoint & GetEnd() const
Definition: class_track.h:123
const int EPSILON
const wxPoint GetPosition() const override
Definition: class_track.h:117
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
virtual const wxPoint GetPosition() const =0
int Distance(const SEG &aSeg) const
Function Distance()
Definition: seg.h:199
MARKER_PCB * DRC::newMarker ( TRACK aTrack,
ZONE_CONTAINER aConflictZone,
int  aErrorCode 
)
private

Definition at line 55 of file drc_marker_functions.cpp.

References SHAPE_POLY_SET::Distance(), EPSILON, TRACK::GetEnd(), ZONE_CONTAINER::GetFilledPolysList(), GetLineLength(), ZONE_CONTAINER::GetPosition(), TRACK::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), ZONE_CONTAINER::IsFilled(), m_pcbEditorFrame, and ZONE_CONTAINER::Outline().

56 {
57  SHAPE_POLY_SET* conflictOutline;
58 
59  if( aConflictZone->IsFilled() )
60  conflictOutline = const_cast<SHAPE_POLY_SET*>( &aConflictZone->GetFilledPolysList() );
61  else
62  conflictOutline = aConflictZone->Outline();
63 
64  wxPoint markerPos;
65  wxPoint pt1 = aTrack->GetPosition();
66  wxPoint pt2 = aTrack->GetEnd();
67 
68  // If the mid-point is in the zone, then that's a fine place for the marker
69  if( conflictOutline->Distance( ( pt1 + pt2 ) / 2 ) == 0 )
70  markerPos = ( pt1 + pt2 ) / 2;
71 
72  // Otherwise do a binary search for a "good enough" marker location
73  else
74  {
75  while( GetLineLength( pt1, pt2 ) > EPSILON )
76  {
77  if( conflictOutline->Distance( pt1 ) < conflictOutline->Distance( pt2 ) )
78  pt2 = ( pt1 + pt2 ) / 2;
79  else
80  pt1 = ( pt1 + pt2 ) / 2;
81  }
82 
83  // Once we're within EPSILON pt1 and pt2 are "equivalent"
84  markerPos = pt1;
85  }
86 
87  return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, markerPos,
88  aTrack, aTrack->GetPosition(),
89  aConflictZone, aConflictZone->GetPosition() );
90 }
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
bool IsFilled() const
Definition: class_zone.h:194
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:241
const wxPoint GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:169
const wxPoint & GetEnd() const
Definition: class_track.h:123
const int EPSILON
const wxPoint GetPosition() const override
Definition: class_track.h:117
Class SHAPE_POLY_SET.
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:557
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
MARKER_PCB * DRC::newMarker ( D_PAD aPad,
BOARD_ITEM aConflictItem,
int  aErrorCode 
)
private

Definition at line 118 of file drc_marker_functions.cpp.

References BOARD_ITEM::GetPosition(), D_PAD::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), and m_pcbEditorFrame.

119 {
120  return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPad->GetPosition(),
121  aPad, aPad->GetPosition(),
122  aConflictItem, aConflictItem->GetPosition() );
123 }
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
virtual const wxPoint GetPosition() const =0
const wxPoint GetPosition() const override
Definition: class_pad.h:220
MARKER_PCB * DRC::newMarker ( const wxPoint &  aPos,
BOARD_ITEM aItem,
int  aErrorCode 
)
private

Function newMarker Creates a marker at a given location.

Parameters
aItemThe reference item.
aPosUsually the position of the item, but could be more specific for a zone.
aErrorCodeAn ID for the particular type of error that is being reported.

Definition at line 126 of file drc_marker_functions.cpp.

References BOARD_ITEM::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), and m_pcbEditorFrame.

127 {
128  return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPos,
129  aItem, aItem->GetPosition(), nullptr, wxPoint() );
130 }
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
virtual const wxPoint GetPosition() const =0
MARKER_PCB * DRC::newMarker ( const wxPoint &  aPos,
BOARD_ITEM aItem,
BOARD_ITEM bItem,
int  aErrorCode 
)
private

Definition at line 133 of file drc_marker_functions.cpp.

References BOARD_ITEM::GetPosition(), EDA_DRAW_FRAME::GetUserUnits(), and m_pcbEditorFrame.

135 {
136  return new MARKER_PCB( m_pcbEditorFrame->GetUserUnits(), aErrorCode, aPos,
137  aItem, aItem->GetPosition(), bItem, bItem->GetPosition() );
138 }
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
virtual const wxPoint GetPosition() const =0
MARKER_PCB * DRC::newMarker ( int  aErrorCode,
const wxString &  aMessage 
)
private

Create a MARKER which will report on a generic problem with the board which is not geographically locatable.

Definition at line 141 of file drc_marker_functions.cpp.

References MARKER_BASE::SetShowNoCoordinate().

142 {
143  MARKER_PCB* marker = new MARKER_PCB( aErrorCode, wxPoint(), aMessage, wxPoint() );
144 
145  marker->SetShowNoCoordinate();
146 
147  return marker;
148 }
void SetShowNoCoordinate()
Definition: marker_base.h:209
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 390 of file drc.cpp.

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

Referenced by DIALOG_DRC_CONTROL::OnStartdrcClick().

391 {
392  // be sure m_pcb is the current board, not a old one
393  // ( the board can be reloaded )
395 
396  if( aMessages )
397  {
398  aMessages->AppendText( _( "Board Outline...\n" ) );
399  wxSafeYield();
400  }
401 
402  testOutline();
403 
404  // someone should have cleared the two lists before calling this.
405  if( !testNetClasses() )
406  {
407  // testing the netclasses is a special case because if the netclasses
408  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
409  // class (a NET) will cause its items such as tracks, vias, and pads
410  // to also fail. So quit after *all* netclass errors have been reported.
411  if( aMessages )
412  aMessages->AppendText( _( "Aborting\n" ) );
413 
414  // update the m_drcDialog listboxes
415  updatePointers();
416 
417  return;
418  }
419 
420  // test pad to pad clearances, nothing to do with tracks, vias or zones.
421  if( m_doPad2PadTest )
422  {
423  if( aMessages )
424  {
425  aMessages->AppendText( _( "Pad clearances...\n" ) );
426  wxSafeYield();
427  }
428 
429  testPad2Pad();
430  }
431 
432  // test clearances between drilled holes
433  if( aMessages )
434  {
435  aMessages->AppendText( _( "Drill clearances...\n" ) );
436  wxSafeYield();
437  }
438 
440 
441  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
442  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
443 
444  if( m_refillZones )
445  {
446  if( aMessages )
447  aMessages->AppendText( _( "Refilling all zones...\n" ) );
448 
449  m_pcbEditorFrame->Fill_All_Zones( caller );
450  }
451  else
452  {
453  if( aMessages )
454  aMessages->AppendText( _( "Checking zone fills...\n" ) );
455 
457  }
458 
459  // test track and via clearances to other tracks, pads, and vias
460  if( aMessages )
461  {
462  aMessages->AppendText( _( "Track clearances...\n" ) );
463  wxSafeYield();
464  }
465 
466  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
467 
468  // test zone clearances to other zones
469  if( aMessages )
470  {
471  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
472  wxSafeYield();
473  }
474 
475  testZones();
476 
477  // find and gather unconnected pads.
478  if( m_doUnconnectedTest )
479  {
480  if( aMessages )
481  {
482  aMessages->AppendText( _( "Unconnected pads...\n" ) );
483  aMessages->Refresh();
484  }
485 
486  testUnconnected();
487  }
488 
489  // find and gather vias, tracks, pads inside keepout areas.
490  if( m_doKeepoutTest )
491  {
492  if( aMessages )
493  {
494  aMessages->AppendText( _( "Keepout areas ...\n" ) );
495  aMessages->Refresh();
496  }
497 
499  }
500 
501  // find and gather vias, tracks, pads inside text boxes.
502  if( aMessages )
503  {
504  aMessages->AppendText( _( "Test texts...\n" ) );
505  wxSafeYield();
506  }
507 
509 
510  // find overlapping courtyard ares.
513  {
514  if( aMessages )
515  {
516  aMessages->AppendText( _( "Courtyard areas...\n" ) );
517  aMessages->Refresh();
518  }
519 
521  }
522 
523  // Check if there are items on disabled layers
525 
526  if( aMessages )
527  {
528  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
529  aMessages->Refresh();
530  }
531 
532  // update the m_drcDialog listboxes
533  updatePointers();
534 
535  if( aMessages )
536  {
537  // no newline on this one because it is last, don't want the window
538  // to unnecessarily scroll.
539  aMessages->AppendText( _( "Finished" ) );
540  }
541 }
bool m_refillZones
Definition: drc.h:186
void testCopperTextAndGraphics()
Definition: drc.cpp:964
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
void testKeepoutAreas()
Definition: drc.cpp:917
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 * GetBoard() const
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
Definition: drc.cpp:1178
BOARD * m_pcb
Definition: drc.h:225
void testDrilledHoles()
Definition: drc.cpp:722
bool m_doKeepoutTest
Definition: drc.h:184
void testZones()
Definition: drc.cpp:882
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:553
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
Definition: drc.cpp:1189
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
bool m_doPad2PadTest
Definition: drc.h:181
void testPad2Pad()
Definition: drc.cpp:678
bool doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1405
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:655
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
Definition: drc.cpp:795
int Fill_All_Zones(wxWindow *aActiveWindow)
Function Fill_All_Zones Fill all zones on the board The old fillings are removed. ...
void testUnconnected()
Definition: drc.cpp:854
bool m_doUnconnectedTest
Definition: drc.h:182
void DRC::SetSettings ( bool  aPad2PadTest,
bool  aUnconnectedTest,
bool  aZonesTest,
bool  aKeepoutTest,
bool  aRefillZones,
bool  aReportAllTrackErrors,
const wxString &  aReportName,
bool  aSaveReport 
)
inline

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

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

Definition at line 517 of file drc.h.

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

521  {
522  m_doPad2PadTest = aPad2PadTest;
523  m_doUnconnectedTest = aUnconnectedTest;
524  m_doZonesTest = aZonesTest;
525  m_doKeepoutTest = aKeepoutTest;
526  m_rptFilename = aReportName;
527  m_doCreateRptFile = aSaveReport;
528  m_refillZones = aRefillZones;
529  m_drcInLegacyRoutingMode = false;
530  m_reportAllTrackErrors = aReportAllTrackErrors;
531  }
bool m_refillZones
Definition: drc.h:186
bool m_doCreateRptFile
Definition: drc.h:185
bool m_doKeepoutTest
Definition: drc.h:184
bool m_doZonesTest
Definition: drc.h:183
bool m_reportAllTrackErrors
Definition: drc.h:187
bool m_doPad2PadTest
Definition: drc.h:181
wxString m_rptFilename
Definition: drc.h:189
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:199
bool m_doUnconnectedTest
Definition: drc.h:182
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 61 of file drc.cpp.

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().

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

Definition at line 1007 of file drc.cpp.

References addMarkerToPcb(), 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(), DRAWSEGMENT::GetShape(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), i, m_pcb, BOARD::m_Track, newMarker(), TRACK::Next(), PCB_VIA_T, DRAWSEGMENT::RebuildBezierToSegmentsPointsList(), S_ARC, S_CIRCLE, S_CURVE, and S_SEGMENT.

Referenced by testCopperTextAndGraphics().

1008 {
1009  std::vector<SEG> itemShape;
1010  int itemWidth = aItem->GetWidth();
1011 
1012  switch( aItem->GetShape() )
1013  {
1014  case S_ARC:
1015  {
1016  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
1017 
1018  auto l = arc.ConvertToPolyline();
1019 
1020  for( int i = 0; i < l.SegmentCount(); i++ )
1021  itemShape.push_back( l.CSegment(i) );
1022 
1023  break;
1024  }
1025 
1026  case S_SEGMENT:
1027  itemShape.push_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
1028  break;
1029 
1030  case S_CIRCLE:
1031  {
1032  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
1033  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
1034 
1035  auto l = circle.ConvertToPolyline();
1036 
1037  for( int i = 0; i < l.SegmentCount(); i++ )
1038  itemShape.push_back( l.CSegment(i) );
1039 
1040  break;
1041  }
1042 
1043  case S_CURVE:
1044  {
1045  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
1046  wxPoint start_pt = aItem->GetBezierPoints()[0];
1047 
1048  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
1049  {
1050  wxPoint end_pt = aItem->GetBezierPoints()[jj];
1051  itemShape.push_back( SEG( start_pt, end_pt ) );
1052  start_pt = end_pt;
1053  }
1054 
1055  break;
1056  }
1057 
1058  default:
1059  break;
1060  }
1061 
1062  // Test tracks and vias
1063  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1064  {
1065  if( !track->IsOnLayer( aItem->GetLayer() ) )
1066  continue;
1067 
1068  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1069  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1070 
1071  for( const auto& itemSeg : itemShape )
1072  {
1073  if( trackAsSeg.Distance( itemSeg ) < minDist )
1074  {
1075  if( track->Type() == PCB_VIA_T )
1076  addMarkerToPcb( newMarker( track, aItem, itemSeg, DRCE_VIA_NEAR_COPPER ) );
1077  else
1078  addMarkerToPcb( newMarker( track, aItem, itemSeg, DRCE_TRACK_NEAR_COPPER ) );
1079  break;
1080  }
1081  }
1082  }
1083 
1084  // Test pads
1085  for( auto pad : m_pcb->GetPads() )
1086  {
1087  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1088  continue;
1089 
1090  const int segmentCount = 18;
1091  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1092  SHAPE_POLY_SET padOutline;
1093 
1094  // We incorporate "minDist" into the pad's outline
1095  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ),
1096  segmentCount, correctionFactor );
1097 
1098  for( const auto& itemSeg : itemShape )
1099  {
1100  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1101  {
1102  addMarkerToPcb( newMarker( pad, aItem, DRCE_PAD_NEAR_COPPER ) );
1103  break;
1104  }
1105  }
1106  }
1107 }
usual segment : line with rounded ends
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:87
BOARD * m_pcb
Definition: drc.h:225
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:86
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
Class SHAPE_POLY_SET.
Arcs (with rounded ends)
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker 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.
TRACK * Next() const
Definition: class_track.h:103
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:88
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=500.0) const
Constructs a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:208
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)
void DRC::testCopperTextAndGraphics ( )
private

Definition at line 964 of file drc.cpp.

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().

965 {
966  // Test copper items for clearance violations with vias, tracks and pads
967 
968  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
969  {
970  if( IsCopperLayer( brdItem->GetLayer() ) )
971  {
972  if( brdItem->Type() == PCB_TEXT_T )
973  testCopperTextItem( brdItem );
974  else if( brdItem->Type() == PCB_LINE_T )
975  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
976  }
977  }
978 
979  for( MODULE* module : m_pcb->Modules() )
980  {
981  TEXTE_MODULE& ref = module->Reference();
982  TEXTE_MODULE& val = module->Value();
983 
984  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
985  testCopperTextItem( &ref );
986 
987  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
988  testCopperTextItem( &val );
989 
990  if( module->IsNetTie() )
991  continue;
992 
993  for( BOARD_ITEM* item = module->GraphicalItemsList(); item; item = item->Next() )
994  {
995  if( IsCopperLayer( item->GetLayer() ) )
996  {
997  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
998  testCopperTextItem( item );
999  else if( item->Type() == PCB_MODULE_EDGE_T )
1000  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
1001  }
1002  }
1003  }
1004 }
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
Definition: drc.cpp:1007
void testCopperTextItem(BOARD_ITEM *aTextItem)
Definition: drc.cpp:1110
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
BOARD * m_pcb
Definition: drc.h:225
BOARD_ITEM * Next() const
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
bool IsVisible() const
Definition: eda_text.h:189
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
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
void DRC::testCopperTextItem ( BOARD_ITEM aTextItem)
private

Definition at line 1110 of file drc.cpp.

References addMarkerToPcb(), SHAPE_POLY_SET::Distance(), DRCE_PAD_NEAR_COPPER, DRCE_TRACK_NEAR_COPPER, DRCE_VIA_NEAR_COPPER, GetCircletoPolyCorrectionFactor(), BOARD_ITEM::GetLayer(), BOARD::GetPads(), EDA_TEXT::GetThickness(), m_pcb, BOARD::m_Track, newMarker(), TRACK::Next(), PCB_VIA_T, and EDA_TEXT::TransformTextShapeToSegmentList().

Referenced by testCopperTextAndGraphics().

1111 {
1112  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1113 
1114  if( text == nullptr )
1115  return;
1116 
1117  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1118  int textWidth = text->GetThickness();
1119 
1120  // So far the bounding box makes up the text-area
1121  text->TransformTextShapeToSegmentList( textShape );
1122 
1123  if( textShape.size() == 0 ) // Should not happen (empty text?)
1124  return;
1125 
1126  // Test tracks and vias
1127  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
1128  {
1129  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1130  continue;
1131 
1132  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1133  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1134 
1135  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1136  {
1137  SEG textSeg( textShape[jj], textShape[jj+1] );
1138 
1139  if( trackAsSeg.Distance( textSeg ) < minDist )
1140  {
1141  if( track->Type() == PCB_VIA_T )
1142  addMarkerToPcb( newMarker( track, aTextItem, textSeg, DRCE_VIA_NEAR_COPPER ) );
1143  else
1144  addMarkerToPcb( newMarker( track, aTextItem, textSeg, DRCE_TRACK_NEAR_COPPER ) );
1145  break;
1146  }
1147  }
1148  }
1149 
1150  // Test pads
1151  for( auto pad : m_pcb->GetPads() )
1152  {
1153  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1154  continue;
1155 
1156  const int segmentCount = 18;
1157  double correctionFactor = GetCircletoPolyCorrectionFactor( segmentCount );
1158  SHAPE_POLY_SET padOutline;
1159 
1160  // We incorporate "minDist" into the pad's outline
1161  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ),
1162  segmentCount, correctionFactor );
1163 
1164  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1165  {
1166  SEG textSeg( textShape[jj], textShape[jj+1] );
1167 
1168  if( padOutline.Distance( textSeg, textWidth ) == 0 )
1169  {
1170  addMarkerToPcb( newMarker( pad, aTextItem, DRCE_PAD_NEAR_COPPER ) );
1171  break;
1172  }
1173  }
1174  }
1175 }
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
#define DRCE_VIA_NEAR_COPPER
via and copper graphic collide or are too close
Definition: drc.h:87
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:167
BOARD * m_pcb
Definition: drc.h:225
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels...
Definition: eda_text.h:127
#define DRCE_TRACK_NEAR_COPPER
track & copper graphic collide or are too close
Definition: drc.h:86
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
Class SHAPE_POLY_SET.
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
Definition: seg.h:36
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
TRACK * Next() const
Definition: class_track.h:103
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
void TransformTextShapeToSegmentList(std::vector< wxPoint > &aCornerBuffer) const
Convert the text shape to a list of segment each segment is stored as 2 wxPoints: the starting point ...
Definition: eda_text.cpp:480
#define DRCE_PAD_NEAR_COPPER
pad and copper graphic collide or are too close
Definition: drc.h:88
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)
void DRC::testDisabledLayers ( )
private

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

Definition at line 1189 of file drc.cpp.

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

Referenced by RunTests().

1190 {
1191  BOARD* board = m_pcbEditorFrame->GetBoard();
1192  wxCHECK( board, /*void*/ );
1193  LSET disabledLayers = board->GetEnabledLayers().flip();
1194 
1195  // Perform the test only for copper layers
1196  disabledLayers &= LSET::AllCuMask();
1197 
1198  auto createMarker = [&]( BOARD_ITEM* aItem )
1199  {
1200  addMarkerToPcb( newMarker( aItem->GetPosition(), aItem, DRCE_DISABLED_LAYER_ITEM ) );
1201  };
1202 
1203  for( auto track : board->Tracks() )
1204  {
1205  if( disabledLayers.test( track->GetLayer() ) )
1206  createMarker( track );
1207  }
1208 
1209  for( auto module : board->Modules() )
1210  {
1211  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1212  {
1213  if( disabledLayers.test( aItem->GetLayer() ) )
1214  createMarker( aItem );
1215  } );
1216  }
1217 
1218  for( auto zone : board->Zones() )
1219  {
1220  if( disabledLayers.test( zone->GetLayer() ) )
1221  createMarker( zone );
1222  }
1223 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
#define DRCE_DISABLED_LAYER_ITEM
item on a disabled layer
Definition: drc.h:96
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
BOARD * GetBoard() const
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:100
Class LSET is a set of PCB_LAYER_IDs.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:255
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker 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:224
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:254
void DRC::testDrilledHoles ( )
private

Definition at line 722 of file drc.cpp.

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().

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

Definition at line 917 of file drc.cpp.

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_pcb, BOARD::m_Track, newMarker(), TRACK::Next(), ZONE_CONTAINER::Outline(), PCB_TRACE_T, and PCB_VIA_T.

Referenced by RunTests().

918 {
919  // Test keepout areas for vias, tracks and pads inside keepout areas
920  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
921  {
922  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
923 
924  if( !area->GetIsKeepout() )
925  {
926  continue;
927  }
928 
929  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
930  {
931  if( segm->Type() == PCB_TRACE_T )
932  {
933  if( !area->GetDoNotAllowTracks() )
934  continue;
935 
936  // Ignore if the keepout zone is not on the same layer
937  if( !area->IsOnLayer( segm->GetLayer() ) )
938  continue;
939 
940  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
941 
942  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
944  }
945  else if( segm->Type() == PCB_VIA_T )
946  {
947  if( ! area->GetDoNotAllowVias() )
948  continue;
949 
950  auto viaLayers = segm->GetLayerSet();
951 
952  if( !area->CommonLayerExists( viaLayers ) )
953  continue;
954 
955  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
957  }
958  }
959  // Test pads: TODO
960  }
961 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set...
Definition: class_zone.cpp:194
virtual bool IsOnLayer(PCB_LAYER_ID) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_zone.cpp:265
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:241
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:83
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:225
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:628
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1026
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:631
TRACK * Next() const
Definition: class_track.h:103
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:997
bool GetDoNotAllowVias() const
Definition: class_zone.h:630
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:84
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
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 655 of file drc.cpp.

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

Referenced by RunTests().

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

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

Definition at line 1178 of file drc.cpp.

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

Referenced by RunTests().

1179 {
1180  wxPoint error_loc( m_pcb->GetBoardEdgesBoundingBox().GetPosition() );
1181  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1182  {
1184  return;
1185  }
1186 }
BOARD * m_pcb
Definition: drc.h:225
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:810
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
#define DRCE_INVALID_OUTLINE
invalid board outline
Definition: drc.h:99
MARKER_PCB * newMarker(TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg, int aErrorCode)
Function newMarker Creates a marker on a track, via or pad.
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...
const wxPoint GetPosition() const
Definition: eda_rect.h:113
SHAPE_POLY_SET m_board_outlines
The board outline including cutouts.
Definition: drc.h:226
void DRC::testPad2Pad ( )
private

Definition at line 678 of file drc.cpp.

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

Referenced by RunTests().

679 {
680  std::vector<D_PAD*> sortedPads;
681 
682  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
683 
684  if( sortedPads.size() == 0 )
685  return;
686 
687  // find the max size of the pads (used to stop the test)
688  int max_size = 0;
689 
690  for( unsigned i = 0; i < sortedPads.size(); ++i )
691  {
692  D_PAD* pad = sortedPads[i];
693 
694  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
695  int radius = pad->GetBoundingRadius();
696 
697  if( radius > max_size )
698  max_size = radius;
699  }
700 
701  // Upper limit of pad list (limit not included)
702  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
703 
704  // Test the pads
705  for( unsigned i = 0; i< sortedPads.size(); ++i )
706  {
707  D_PAD* pad = sortedPads[i];
708 
709  int x_limit = max_size + pad->GetClearance() +
710  pad->GetBoundingRadius() + pad->GetPosition().x;
711 
712  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
713  {
714  wxASSERT( m_currentMarker );
716  m_currentMarker = nullptr;
717  }
718  }
719 }
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:225
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:100
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:612
bool doPadToPadsDrc(D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Test the clearance between aRefPad and other pads.
Definition: drc.cpp:1273
MARKER_PCB * m_currentMarker
Definition: drc.h:191
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:562
const wxPoint GetPosition() const override
Definition: class_pad.h:220
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 795 of file drc.cpp.

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

Referenced by RunTests().

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

Definition at line 854 of file drc.cpp.

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

Referenced by ListUnconnectedPads(), and RunTests().

855 {
856 
857  auto connectivity = m_pcb->GetConnectivity();
858 
859  connectivity->Clear();
860  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
861  connectivity->RecalculateRatsnest();
862 
863  std::vector<CN_EDGE> edges;
864  connectivity->GetUnconnectedEdges( edges );
865 
866  for( const auto& edge : edges )
867  {
868  auto src = edge.GetSourcePos();
869  auto dst = edge.GetTargetPos();
870 
871  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
873  edge.GetSourceNode()->Parent(),
874  wxPoint( src.x, src.y ),
875  edge.GetTargetNode()->Parent(),
876  wxPoint( dst.x, dst.y ) ) );
877 
878  }
879 }
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:47
BOARD * m_pcb
Definition: drc.h:225
EDA_UNITS_T GetUserUnits() const override
Return the user units currently in use.
Definition: draw_frame.h:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:229
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:297
void DRC::testZones ( )
private

Definition at line 882 of file drc.cpp.

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_pcb, newMarker(), and TestZoneToZoneOutline().

Referenced by RunTests().

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

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_pcbEditorFrame, 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().

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

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

Definition at line 553 of file drc.cpp.

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

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

554 {
555  // update my pointers, m_pcbEditorFrame is the only unchangeable one
557 
558  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
559  {
564 
566  }
567 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:227
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:663
BOARD * GetBoard() const
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc.h:225
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:284
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:224
Class DRC_LIST_UNCONNECTED is an implementation of the interface named DRC_ITEM_LIST which uses a vec...
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:229

Friends And Related Function Documentation

friend class DIALOG_DRC_CONTROL
friend

Definition at line 176 of file drc.h.

Referenced by ShowDRCDialog().

Member Data Documentation

SHAPE_POLY_SET DRC::m_board_outlines
private

The board outline including cutouts.

Definition at line 226 of file drc.h.

Referenced by doTrackDrc(), and testOutline().

bool DRC::m_doCreateRptFile
private

Definition at line 185 of file drc.h.

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

bool DRC::m_doKeepoutTest
private

Definition at line 184 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doPad2PadTest
private

Definition at line 181 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doUnconnectedTest
private

Definition at line 182 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doZonesTest
private

Definition at line 183 of file drc.h.

Referenced by DRC().

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 227 of file drc.h.

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

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

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

wxPoint DRC::m_padToTestPos
private

Definition at line 205 of file drc.h.

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

PCB_EDIT_FRAME* DRC::m_pcbEditorFrame
private
bool DRC::m_refillZones
private

Definition at line 186 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_reportAllTrackErrors
private

Definition at line 187 of file drc.h.

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

wxString DRC::m_rptFilename
private

Definition at line 189 of file drc.h.

Referenced by DestroyDRCDialog(), and ShowDRCDialog().

double DRC::m_segmAngle
private

Definition at line 213 of file drc.h.

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

wxPoint DRC::m_segmEnd
private

Definition at line 206 of file drc.h.

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

int DRC::m_segmLength
private

Definition at line 214 of file drc.h.

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

DRC_LIST DRC::m_unconnected
private

list of unconnected pads, as DRC_ITEMs

Definition at line 229 of file drc.h.

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

int DRC::m_xcliphi
private

Definition at line 221 of file drc.h.

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

int DRC::m_xcliplo
private

Definition at line 219 of file drc.h.

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

int DRC::m_ycliphi
private

Definition at line 222 of file drc.h.

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

int DRC::m_ycliplo
private

Definition at line 220 of file drc.h.

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


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