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 Drc (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 Drc (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 DrcBlind (TRACK *aRefSeg, TRACK *aList)
 Test the current segment and returns the result. More...
 
int TestZoneToZoneOutline (ZONE_CONTAINER *aZone, bool aCreateMarkers)
 
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 aCourtyardTest, bool aCourtyardMissingTest, 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_PCBfillMarker (const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
 Creates a marker and fills it in with information but does not add it to the BOARD. More...
 
MARKER_PCBfillMarker (D_PAD *aPad, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
 
MARKER_PCBfillMarker (ZONE_CONTAINER *aArea, int aErrorCode, MARKER_PCB *fillMe)
 
MARKER_PCBfillMarker (const wxPoint &aPos, int aErrorCode, const wxString &aMessage, MARKER_PCB *fillMe)
 
MARKER_PCBfillMarker (const ZONE_CONTAINER *aArea, const wxPoint &aPos, int aErrorCode, MARKER_PCB *fillMe)
 Create a marker and fills it in with information but do not add it to the BOARD. More...
 
MARKER_PCBfillMarker (int aErrorCode, const wxString &aMessage, MARKER_PCB *fillMe)
 Fill 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 testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testTexts ()
 
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_doFootprintOverlapping
 
bool m_doNoCourtyardDefined
 
bool m_refillZones
 
bool m_reportAllTrackErrors
 
wxString m_rptFilename
 
MARKER_PCBm_currentMarker
 
bool m_abortDRC
 
bool m_drcInProgress
 
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
 
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 162 of file drc.h.

Constructor & Destructor Documentation

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 122 of file drc.cpp.

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

123 {
124  m_pcbEditorFrame = aPcbWindow;
125  m_pcb = aPcbWindow->GetBoard();
126  m_drcDialog = NULL;
127 
128  // establish initial values for everything:
129  m_doPad2PadTest = true; // enable pad to pad clearance tests
130  m_doUnconnectedTest = true; // enable unconnected tests
131  m_doZonesTest = true; // enable zone to items clearance tests
132  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
133  m_doFootprintOverlapping = true; // enable courtyards areas overlap tests
134  m_doNoCourtyardDefined = true; // enable missing courtyard in footprint warning
135  m_abortDRC = false;
136  m_drcInProgress = false;
137  m_refillZones = false; // Only fill zones if requested by user.
138  m_reportAllTrackErrors = false;
139  m_doCreateRptFile = false;
140 
141  // m_rptFilename set to empty by its constructor
142 
143  m_currentMarker = NULL;
144 
145  m_segmAngle = 0;
146  m_segmLength = 0;
147 
148  m_xcliplo = 0;
149  m_ycliplo = 0;
150  m_xcliphi = 0;
151  m_ycliphi = 0;
152 }
bool m_refillZones
Definition: drc.h:176
bool m_doNoCourtyardDefined
Definition: drc.h:175
bool m_doCreateRptFile
Definition: drc.h:173
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:211
int m_ycliplo
Definition: drc.h:205
int m_ycliphi
Definition: drc.h:207
int m_segmLength
Definition: drc.h:199
BOARD * GetBoard() const
BOARD * m_pcb
Definition: drc.h:210
bool m_doFootprintOverlapping
Definition: drc.h:174
bool m_doKeepoutTest
Definition: drc.h:172
bool m_doZonesTest
Definition: drc.h:171
bool m_abortDRC
Definition: drc.h:183
bool m_drcInProgress
Definition: drc.h:184
bool m_reportAllTrackErrors
Definition: drc.h:177
int m_xcliphi
Definition: drc.h:206
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
bool m_doPad2PadTest
Definition: drc.h:169
MARKER_PCB * m_currentMarker
Definition: drc.h:181
int m_xcliplo
Definition: drc.h:204
bool m_doUnconnectedTest
Definition: drc.h:170
double m_segmAngle
Definition: drc.h:198
DRC::~DRC ( )

Definition at line 155 of file drc.cpp.

References i, and m_unconnected.

156 {
157  // maybe someday look at pointainer.h <- google for "pointainer.h"
158  for( unsigned i = 0; i<m_unconnected.size(); ++i )
159  delete m_unconnected[i];
160 }
size_t i
Definition: json11.cpp:597
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:213

Member Function Documentation

void DRC::addMarkerToPcb ( MARKER_PCB aMarker)
private

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

Definition at line 98 of file drc.cpp.

References COMMIT::Add(), m_pcbEditorFrame, and BOARD_COMMIT::Push().

Referenced by doFootprintOverlappingDrc(), doNetClass(), testKeepoutAreas(), testPad2Pad(), testTexts(), testTracks(), and testZones().

99 {
100  BOARD_COMMIT commit( m_pcbEditorFrame );
101  commit.Add( aMarker );
102  commit.Push( wxEmptyString, false, false );
103 }
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
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 770 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(), D_PAD::ShapePos(), wxPoint::x, and wxPoint::y.

Referenced by doPadToPadsDrc().

771 {
772  int dist;
773  double pad_angle;
774 
775  // Get the clearance between the 2 pads. this is the min distance between aRefPad and aPad
776  int dist_min = aRefPad->GetClearance( aPad );
777 
778  // relativePadPos is the aPad shape position relative to the aRefPad shape position
779  wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos();
780 
781  dist = KiROUND( EuclideanNorm( relativePadPos ) );
782 
783  // Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
784  int delta = dist - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius();
785 
786  if( delta >= dist_min )
787  return true;
788 
789  /* Here, pads are near and DRC depend on the pad shapes
790  * We must compare distance using a fine shape analysis
791  * Because a circle or oval shape is the easier shape to test, try to have
792  * aRefPad shape type = PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
793  * if aRefPad = TRAP. and aPad = RECT, also swap pads
794  * Swap aRefPad and aPad if needed
795  */
796  bool swap_pads;
797  swap_pads = false;
798 
799  // swap pads to make comparisons easier
800  // Note also a ROUNDRECT pad with a corner radius = r can be considered as
801  // a smaller RECT (size - 2*r) with a clearance increased by r
802  // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
803  if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
804  {
805  // pad ref shape is here oval, rect, roundrect, trapezoid or custom
806  switch( aPad->GetShape() )
807  {
808  case PAD_SHAPE_CIRCLE:
809  swap_pads = true;
810  break;
811 
812  case PAD_SHAPE_OVAL:
813  swap_pads = true;
814  break;
815 
816  case PAD_SHAPE_RECT:
817  case PAD_SHAPE_ROUNDRECT:
818  if( aRefPad->GetShape() != PAD_SHAPE_OVAL )
819  swap_pads = true;
820  break;
821 
822  case PAD_SHAPE_TRAPEZOID:
823  case PAD_SHAPE_CUSTOM:
824  break;
825  }
826  }
827 
828  if( swap_pads )
829  {
830  std::swap( aRefPad, aPad );
831  relativePadPos = -relativePadPos;
832  }
833 
834  // corners of aRefPad (used only for rect/roundrect/trap pad)
835  wxPoint polyref[4];
836  // corners of aRefPad (used only for custom pad)
837  SHAPE_POLY_SET polysetref;
838 
839  // corners of aPad (used only for rect/roundrect/trap pad)
840  wxPoint polycompare[4];
841  // corners of aPad (used only custom pad)
842  SHAPE_POLY_SET polysetcompare;
843 
844  /* Because pad exchange, aRefPad shape is PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL,
845  * if one of the 2 pads was a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
846  * Therefore, if aRefPad is a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID,
847  * aPad is also a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID
848  */
849  bool diag = true;
850 
851  switch( aRefPad->GetShape() )
852  {
853  case PAD_SHAPE_CIRCLE:
854 
855  /* One can use checkClearanceSegmToPad to test clearance
856  * aRefPad is like a track segment with a null length and a witdth = GetSize().x
857  */
858  m_segmLength = 0;
859  m_segmAngle = 0;
860 
861  m_segmEnd.x = m_segmEnd.y = 0;
862 
863  m_padToTestPos = relativePadPos;
864  diag = checkClearanceSegmToPad( aPad, aRefPad->GetSize().x, dist_min );
865  break;
866 
867  case PAD_SHAPE_TRAPEZOID:
868  case PAD_SHAPE_ROUNDRECT:
869  case PAD_SHAPE_RECT:
870  case PAD_SHAPE_CUSTOM:
871  // pad_angle = pad orient relative to the aRefPad orient
872  pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
873  NORMALIZE_ANGLE_POS( pad_angle );
874 
875  if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
876  {
877  int padRadius = aRefPad->GetRoundRectCornerRadius();
878  dist_min += padRadius;
879  GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ),
880  aRefPad->GetSize(), aRefPad->GetOrientation() );
881  }
882  else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM )
883  {
884  polysetref.Append( aRefPad->GetCustomShapeAsPolygon() );
885 
886  // The reference pad can be rotated. calculate the rotated
887  // coordiantes ( note, the ref pad position is the origin of
888  // coordinates for this drc test)
889  aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref,
890  wxPoint( 0, 0 ), aRefPad->GetOrientation() );
891  }
892  else
893  {
894  // BuildPadPolygon has meaning for rect a trapeziod shapes
895  // and returns the 4 corners
896  aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
897  }
898 
899  switch( aPad->GetShape() )
900  {
901  case PAD_SHAPE_ROUNDRECT:
902  case PAD_SHAPE_RECT:
903  case PAD_SHAPE_TRAPEZOID:
904  case PAD_SHAPE_CUSTOM:
905  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
906  {
907  int padRadius = aPad->GetRoundRectCornerRadius();
908  dist_min += padRadius;
909  GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos,
910  aPad->GetSize(), aPad->GetOrientation() );
911  }
912  else if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
913  {
914  polysetcompare.Append( aPad->GetCustomShapeAsPolygon() );
915 
916  // The pad to compare can be rotated. calculate the rotated
917  // coordinattes ( note, the pad to compare position
918  // is the relativePadPos for this drc test
919  aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare,
920  relativePadPos, aPad->GetOrientation() );
921  }
922  else
923  {
924  aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() );
925 
926  // Move aPad shape to relativePadPos
927  for( int ii = 0; ii < 4; ii++ )
928  polycompare[ii] += relativePadPos;
929  }
930  // And now test polygons: We have 3 cases:
931  // one poly is complex and the other is basic (has only 4 corners)
932  // both polys are complex
933  // both polys are basic (have only 4 corners) the most usual case
934  if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0)
935  {
936  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
937  // And now test polygons:
938  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
939  polycompare, 4, dist_min ) )
940  diag = false;
941  }
942  else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount())
943  {
944  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
945  // And now test polygons:
946  if( !poly2polyDRC( (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(),
947  polyref, 4, dist_min ) )
948  diag = false;
949  }
950  else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() )
951  {
952  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
953  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
954 
955  // And now test polygons:
956  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
957  (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), dist_min ) )
958  diag = false;
959  }
960  else if( !poly2polyDRC( polyref, 4, polycompare, 4, dist_min ) )
961  diag = false;
962  break;
963 
964  default:
965  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() );
966  break;
967  }
968  break;
969 
970  case PAD_SHAPE_OVAL: /* an oval pad is like a track segment */
971  {
972  /* Create a track segment with same dimensions as the oval aRefPad
973  * and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
974  */
975  int segm_width;
976  m_segmAngle = aRefPad->GetOrientation(); // Segment orient.
977 
978  if( aRefPad->GetSize().y < aRefPad->GetSize().x ) // Build an horizontal equiv segment
979  {
980  segm_width = aRefPad->GetSize().y;
981  m_segmLength = aRefPad->GetSize().x - aRefPad->GetSize().y;
982  }
983  else // Vertical oval: build an horizontal equiv segment and rotate 90.0 deg
984  {
985  segm_width = aRefPad->GetSize().x;
986  m_segmLength = aRefPad->GetSize().y - aRefPad->GetSize().x;
987  m_segmAngle += 900;
988  }
989 
990  /* the start point must be 0,0 and currently relativePadPos
991  * is relative the center of pad coordinate */
992  wxPoint segstart;
993  segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
994 
995  RotatePoint( &segstart, m_segmAngle ); // actual start point coordinate of the equivalent segment
996  // Calculate segment end position relative to the segment origin
997  m_segmEnd.x = -2 * segstart.x;
998  m_segmEnd.y = -2 * segstart.y;
999 
1000  // Recalculate the equivalent segment angle in 0,1 degrees
1001  // to prepare a call to checkClearanceSegmToPad()
1003 
1004  // move pad position relative to the segment origin
1005  m_padToTestPos = relativePadPos - segstart;
1006 
1007  // Use segment to pad check to test the second pad:
1008  diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
1009  break;
1010  }
1011 
1012  default:
1013  wxMessageBox( wxT( "DRC::checkClearancePadToPad: unknown pad shape" ) );
1014  break;
1015  }
1016 
1017  return diag;
1018 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
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:518
static const int dist[10][10]
Definition: dist.cpp:57
int m_segmLength
Definition: drc.h:199
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:190
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:593
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:191
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:546
wxPoint ShapePos() const
Definition: class_pad.cpp:500
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
double m_segmAngle
Definition: drc.h:198
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 1026 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(), RotatePoint(), wxPoint::x, and wxPoint::y.

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

1027 {
1028  // Note:
1029  // we are using a horizontal segment for test, because we know here
1030  // only the length and orientation+ of the segment
1031  // Therefore the coordinates of the shape of pad to compare
1032  // must be calculated in a axis system rotated by m_segmAngle
1033  // and centered to the segment origin, before they can be tested
1034  // against the segment
1035  // We are using:
1036  // m_padToTestPos the position of the pad shape in this axis system
1037  // m_segmAngle the axis system rotation
1038 
1039  int segmHalfWidth = aSegmentWidth / 2;
1040  int distToLine = segmHalfWidth + aMinDist;
1041 
1042  wxSize padHalfsize; // half dimension of the pad
1043 
1044  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1045  {
1046  // For a custom pad, the pad size has no meaning, we only can
1047  // use the bounding radius
1048  padHalfsize.x = padHalfsize.y = aPad->GetBoundingRadius();
1049  }
1050  else
1051  {
1052  padHalfsize = aPad->GetSize() / 2;
1053  }
1054 
1055  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
1056  {
1057  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
1058  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
1059  }
1060 
1061  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1062  {
1063  /* Easy case: just test the distance between segment and pad centre
1064  * calculate pad coordinates in the X,Y axis with X axis = segment to test
1065  */
1067  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
1068  }
1069 
1070  /* calculate the bounding box of the pad, including the clearance and the segment width
1071  * if the line from 0 to m_segmEnd does not intersect this bounding box,
1072  * the clearance is always OK
1073  * But if intersect, a better analysis of the pad shape must be done.
1074  */
1075  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
1076  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
1077  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
1078  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
1079 
1080  wxPoint startPoint( 0, 0 );
1081  wxPoint endPoint = m_segmEnd;
1082 
1083  double orient = aPad->GetOrientation();
1084 
1085  RotatePoint( &startPoint, m_padToTestPos, -orient );
1086  RotatePoint( &endPoint, m_padToTestPos, -orient );
1087 
1088  if( checkLine( startPoint, endPoint ) )
1089  return true;
1090 
1091  /* segment intersects the bounding box. But there is not always a DRC error.
1092  * A fine analysis of the pad shape must be done.
1093  */
1094  switch( aPad->GetShape() )
1095  {
1096  case PAD_SHAPE_CIRCLE:
1097  // This case was already tested, so it cannot be found here.
1098  // it is here just to avoid compil warning, and to remember
1099  // it is already tested.
1100  return false;
1101 
1102  case PAD_SHAPE_OVAL:
1103  {
1104  /* an oval is a complex shape, but is a rectangle and 2 circles
1105  * these 3 basic shapes are more easy to test.
1106  *
1107  * In calculations we are using a vertical or horizontal oval shape
1108  * (i.e. a vertical or horizontal rounded segment)
1109  */
1110  wxPoint cstart = m_padToTestPos;
1111  wxPoint cend = m_padToTestPos; // center of each circle
1112  int delta = std::abs( padHalfsize.y - padHalfsize.x );
1113  int radius = std::min( padHalfsize.y, padHalfsize.x );
1114 
1115  if( padHalfsize.x > padHalfsize.y ) // horizontal equivalent segment
1116  {
1117  cstart.x -= delta;
1118  cend.x += delta;
1119  // Build the rectangular clearance area between the two circles
1120  // the rect starts at cstart.x and ends at cend.x and its height
1121  // is (radius + distToLine)*2
1122  m_xcliplo = cstart.x;
1123  m_ycliplo = cstart.y - radius - distToLine;
1124  m_xcliphi = cend.x;
1125  m_ycliphi = cend.y + radius + distToLine;
1126  }
1127  else // vertical equivalent segment
1128  {
1129  cstart.y -= delta;
1130  cend.y += delta;
1131  // Build the rectangular clearance area between the two circles
1132  // the rect starts at cstart.y and ends at cend.y and its width
1133  // is (radius + distToLine)*2
1134  m_xcliplo = cstart.x - distToLine - radius;
1135  m_ycliplo = cstart.y;
1136  m_xcliphi = cend.x + distToLine + radius;
1137  m_ycliphi = cend.y;
1138  }
1139 
1140  // Test the rectangular clearance area between the two circles (the rounded ends)
1141  // If the segment legth is zero, only check the endpoints, skip the rectangle
1142  if( m_segmLength && !checkLine( startPoint, endPoint ) )
1143  {
1144  return false;
1145  }
1146 
1147  // test the first end
1148  // Calculate the actual position of the circle, given the pad orientation:
1149  RotatePoint( &cstart, m_padToTestPos, orient );
1150 
1151  // Calculate the actual position of the circle in the new X,Y axis, relative
1152  // to the segment:
1153  RotatePoint( &cstart, m_segmAngle );
1154 
1155  if( !checkMarginToCircle( cstart, radius + distToLine, m_segmLength ) )
1156  {
1157  return false;
1158  }
1159 
1160  // test the second end
1161  RotatePoint( &cend, m_padToTestPos, orient );
1162  RotatePoint( &cend, m_segmAngle );
1163 
1164  if( !checkMarginToCircle( cend, radius + distToLine, m_segmLength ) )
1165  {
1166  return false;
1167  }
1168  }
1169  break;
1170 
1171  case PAD_SHAPE_ROUNDRECT:
1172  {
1173  // a round rect is a smaller rect, with a clearance augmented by the corners radius
1174  int r = aPad->GetRoundRectCornerRadius();
1175  padHalfsize.x -= r;
1176  padHalfsize.y -= r;
1177  distToLine += r;
1178  }
1179  // Fall through
1180  case PAD_SHAPE_RECT:
1181  // the area to test is a rounded rectangle.
1182  // this can be done by testing 2 rectangles and 4 circles (the corners)
1183 
1184  // Testing the first rectangle dimx + distToLine, dimy:
1185  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
1186  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
1187  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
1188  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
1189 
1190  if( !checkLine( startPoint, endPoint ) )
1191  return false;
1192 
1193  // Testing the second rectangle dimx , dimy + distToLine
1194  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
1195  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
1196  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
1197  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
1198 
1199  if( !checkLine( startPoint, endPoint ) )
1200  return false;
1201 
1202  // testing the 4 circles which are the clearance area of each corner:
1203 
1204  // testing the left top corner of the rectangle
1205  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1206  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1207  RotatePoint( &startPoint, m_padToTestPos, orient );
1208  RotatePoint( &startPoint, m_segmAngle );
1209 
1210  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1211  return false;
1212 
1213  // testing the right top corner of the rectangle
1214  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1215  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1216  RotatePoint( &startPoint, m_padToTestPos, orient );
1217  RotatePoint( &startPoint, m_segmAngle );
1218 
1219  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1220  return false;
1221 
1222  // testing the left bottom corner of the rectangle
1223  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1224  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1225  RotatePoint( &startPoint, m_padToTestPos, orient );
1226  RotatePoint( &startPoint, m_segmAngle );
1227 
1228  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1229  return false;
1230 
1231  // testing the right bottom corner of the rectangle
1232  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1233  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1234  RotatePoint( &startPoint, m_padToTestPos, orient );
1235  RotatePoint( &startPoint, m_segmAngle );
1236 
1237  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1238  return false;
1239 
1240  break;
1241 
1242  case PAD_SHAPE_TRAPEZOID:
1243  {
1244  wxPoint poly[4];
1245  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
1246 
1247  // Move shape to m_padToTestPos
1248  for( int ii = 0; ii < 4; ii++ )
1249  {
1250  poly[ii] += m_padToTestPos;
1251  RotatePoint( &poly[ii], m_segmAngle );
1252  }
1253 
1254  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ),
1255  wxPoint(m_segmLength,0), distToLine ) )
1256  return false;
1257  }
1258  break;
1259 
1260  case PAD_SHAPE_CUSTOM:
1261  {
1262  SHAPE_POLY_SET polyset;
1263  polyset.Append( aPad->GetCustomShapeAsPolygon() );
1264  // The pad can be rotated. calculate the coordinates
1265  // relatives to the segment being tested
1266  // Note, the pad position relative to the segment origin
1267  // is m_padToTestPos
1268  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1269  m_padToTestPos, orient );
1270 
1271  // Rotate all coordinates by m_segmAngle, because the segment orient
1272  // is m_segmAngle
1273  // we are using a horizontal segment for test, because we know here
1274  // only the lenght and orientation+ of the segment
1275  // therefore all coordinates of the pad to test must be rotated by
1276  // m_segmAngle (they are already relative to the segment origin)
1277  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1278  wxPoint( 0, 0 ), m_segmAngle );
1279 
1280  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1281 
1282  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1283  refpoly.PointCount(),
1284  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1285  distToLine ) )
1286  return false;
1287  }
1288  break;
1289  }
1290 
1291  return true;
1292 }
int m_ycliplo
Definition: drc.h:205
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:518
int m_ycliphi
Definition: drc.h:207
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc.h:199
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
wxPoint m_padToTestPos
Definition: drc.h:190
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:593
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:206
wxPoint m_segmEnd
Definition: drc.h:191
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:204
double m_segmAngle
Definition: drc.h:198
#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 1354 of file drc_clearance_test_functions.cpp.

References m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, USCALE(), WHEN_INSIDE, WHEN_OUTSIDE, wxPoint::x, and wxPoint::y.

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1355 {
1356 #define WHEN_OUTSIDE return true
1357 #define WHEN_INSIDE
1358  int temp;
1359 
1360  if( aSegStart.x > aSegEnd.x )
1361  std::swap( aSegStart, aSegEnd );
1362 
1363  if( (aSegEnd.x <= m_xcliplo) || (aSegStart.x >= m_xcliphi) )
1364  {
1365  WHEN_OUTSIDE;
1366  }
1367 
1368  if( aSegStart.y < aSegEnd.y )
1369  {
1370  if( (aSegEnd.y <= m_ycliplo) || (aSegStart.y >= m_ycliphi) )
1371  {
1372  WHEN_OUTSIDE;
1373  }
1374 
1375  if( aSegStart.y < m_ycliplo )
1376  {
1377  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1378  (aSegEnd.y - aSegStart.y) );
1379 
1380  if( (aSegStart.x += temp) >= m_xcliphi )
1381  {
1382  WHEN_OUTSIDE;
1383  }
1384 
1385  aSegStart.y = m_ycliplo;
1386  WHEN_INSIDE;
1387  }
1388 
1389  if( aSegEnd.y > m_ycliphi )
1390  {
1391  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1392  (aSegEnd.y - aSegStart.y) );
1393 
1394  if( (aSegEnd.x -= temp) <= m_xcliplo )
1395  {
1396  WHEN_OUTSIDE;
1397  }
1398 
1399  aSegEnd.y = m_ycliphi;
1400  WHEN_INSIDE;
1401  }
1402 
1403  if( aSegStart.x < m_xcliplo )
1404  {
1405  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1406  (aSegEnd.x - aSegStart.x) );
1407  aSegStart.y += temp;
1408  aSegStart.x = m_xcliplo;
1409  WHEN_INSIDE;
1410  }
1411 
1412  if( aSegEnd.x > m_xcliphi )
1413  {
1414  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1415  (aSegEnd.x - aSegStart.x) );
1416  aSegEnd.y -= temp;
1417  aSegEnd.x = m_xcliphi;
1418  WHEN_INSIDE;
1419  }
1420  }
1421  else
1422  {
1423  if( (aSegStart.y <= m_ycliplo) || (aSegEnd.y >= m_ycliphi) )
1424  {
1425  WHEN_OUTSIDE;
1426  }
1427 
1428  if( aSegStart.y > m_ycliphi )
1429  {
1430  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1431  (aSegStart.y - aSegEnd.y) );
1432 
1433  if( (aSegStart.x += temp) >= m_xcliphi )
1434  {
1435  WHEN_OUTSIDE;
1436  }
1437 
1438  aSegStart.y = m_ycliphi;
1439  WHEN_INSIDE;
1440  }
1441 
1442  if( aSegEnd.y < m_ycliplo )
1443  {
1444  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1445  (aSegStart.y - aSegEnd.y) );
1446 
1447  if( (aSegEnd.x -= temp) <= m_xcliplo )
1448  {
1449  WHEN_OUTSIDE;
1450  }
1451 
1452  aSegEnd.y = m_ycliplo;
1453  WHEN_INSIDE;
1454  }
1455 
1456  if( aSegStart.x < m_xcliplo )
1457  {
1458  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1459  (aSegEnd.x - aSegStart.x) );
1460  aSegStart.y -= temp;
1461  aSegStart.x = m_xcliplo;
1462  WHEN_INSIDE;
1463  }
1464 
1465  if( aSegEnd.x > m_xcliphi )
1466  {
1467  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1468  (aSegEnd.x - aSegStart.x) );
1469  aSegEnd.y += temp;
1470  aSegEnd.x = m_xcliphi;
1471  WHEN_INSIDE;
1472  }
1473  }
1474 
1475  // Do not divide here to avoid rounding errors
1476  if( ( (aSegEnd.x + aSegStart.x) < m_xcliphi * 2 )
1477  && ( (aSegEnd.x + aSegStart.x) > m_xcliplo * 2) \
1478  && ( (aSegEnd.y + aSegStart.y) < m_ycliphi * 2 )
1479  && ( (aSegEnd.y + aSegStart.y) > m_ycliplo * 2 ) )
1480  {
1481  return false;
1482  }
1483  else
1484  {
1485  return true;
1486  }
1487 }
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
int m_ycliplo
Definition: drc.h:205
int m_ycliphi
Definition: drc.h:207
int m_xcliphi
Definition: drc.h:206
#define WHEN_INSIDE
int m_xcliplo
Definition: drc.h:204
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 1301 of file drc_clearance_test_functions.cpp.

References abs, EuclideanNorm(), wxPoint::x, and wxPoint::y.

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1302 {
1303  if( abs( aCentre.y ) >= aRadius ) // trivial case
1304  return true;
1305 
1306  // Here, distance between aCentre and X axis is < aRadius
1307  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1308  {
1309  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1310  return false; // aCentre is between the starting point and the ending point of the segm
1311 
1312  if( aCentre.x > aLength ) // aCentre is after the ending point
1313  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1314 
1315  if( EuclideanNorm( aCentre ) < aRadius )
1316  // distance between aCentre and the starting point or the ending point is < aRadius
1317  return false;
1318  }
1319 
1320  return true;
1321 }
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 106 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(), DIALOG_DRC_CONTROL::OnOkClick(), and DIALOG_PLOT::onRunDRC().

107 {
108  if( m_drcDialog )
109  {
110  if( aReason == wxID_OK )
111  {
112  // if user clicked OK, save his choices in this DRC object.
114  }
115 
116  m_drcDialog->Destroy();
117  m_drcDialog = NULL;
118  }
119 }
bool m_doCreateRptFile
Definition: drc.h:173
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:211
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:188
wxString m_rptFilename
Definition: drc.h:179
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 670 of file drc_clearance_test_functions.cpp.

References SEG::A, SEG::B, SHAPE_POLY_SET::Contains(), COPPERAREA_CLOSE_TO_COPPERAREA, COPPERAREA_INSIDE_COPPERAREA, fillMarker(), 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, ZONE_CONTAINER::Outline(), SHAPE_POLY_SET::Polygon(), SHAPE_LINE_CHAIN::Segment(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by Drc().

671 {
672  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
673  return true;
674  // Get polygon, contour and vertex index.
676 
677  // If the vertex does not exist, there is no conflict
678  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
679  return true;
680 
681  // Retrieve the selected contour
682  SHAPE_LINE_CHAIN contour;
683  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
684 
685  // Retrieve the segment that starts at aCornerIndex-th corner.
686  SEG selectedSegment = contour.Segment( index.m_vertex );
687 
688  VECTOR2I start = selectedSegment.A;
689  VECTOR2I end = selectedSegment.B;
690 
691  // iterate through all areas
692  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
693  {
694  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
695  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
696  aArea->GetZoneClearance() );
697 
698  // test for same layer
699  if( area_to_test->GetLayer() != aArea->GetLayer() )
700  continue;
701 
702  // Test for same net
703  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
704  continue;
705 
706  // test for same priority
707  if( area_to_test->GetPriority() != aArea->GetPriority() )
708  continue;
709 
710  // test for same type
711  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
712  continue;
713 
714  // For keepout, there is no clearance, so use a minimal value for it
715  // use 1, not 0 as value to avoid some issues in tests
716  if( area_to_test->GetIsKeepout() )
717  zone_clearance = 1;
718 
719  // test for ending line inside area_to_test
720  if( area_to_test->Outline()->Contains( end ) )
721  {
722  // COPPERAREA_COPPERAREA error: corner inside copper area
723  m_currentMarker = fillMarker( aArea, static_cast<wxPoint>( end ),
725  m_currentMarker );
726  return false;
727  }
728 
729  // now test spacing between areas
730  int ax1 = start.x;
731  int ay1 = start.y;
732  int ax2 = end.x;
733  int ay2 = end.y;
734 
735  // Iterate through all edges in the polygon.
737  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
738  {
739  SEG segment = *iterator;
740 
741  int bx1 = segment.A.x;
742  int by1 = segment.A.y;
743  int bx2 = segment.B.x;
744  int by2 = segment.B.y;
745 
746  int x, y; // variables containing the intersecting point coordinates
747  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
748  0,
749  ax1, ay1, ax2, ay2,
750  0,
751  zone_clearance,
752  &x, &y );
753 
754  if( d < zone_clearance )
755  {
756  // COPPERAREA_COPPERAREA error : edge intersect or too close
757  m_currentMarker = fillMarker( aArea, wxPoint( x, y ),
759  m_currentMarker );
760  return false;
761  }
762 
763  }
764  }
765 
766  return true;
767 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
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:236
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.
#define COPPERAREA_INSIDE_COPPERAREA
copper area outlines intersect
Definition: drc.h:65
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)
BOARD * m_pcb
Definition: drc.h:210
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:602
#define COPPERAREA_CLOSE_TO_COPPERAREA
copper area outlines are too close
Definition: drc.h:66
bool GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Function GetRelativeIndices.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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:982
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:46
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:101
int GetZoneClearance() const
Definition: class_zone.h:192
VECTOR2I B
Definition: seg.h:47
bool DRC::doFootprintOverlappingDrc ( )
private

Test for footprint courtyard overlaps.

Returns
bool - false if DRC error or true if OK

Definition at line 1154 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, fillMarker(), m_currentMarker, m_doFootprintOverlapping, m_doNoCourtyardDefined, BOARD::m_Modules, m_pcb, 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().

1155 {
1156  // Detects missing (or malformed) footprint courtyard,
1157  // and for footprint with courtyard, courtyards overlap.
1158  wxString msg;
1159  bool success = true;
1160 
1161  // Update courtyard polygons, and test for missing courtyard definition:
1162  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1163  {
1164  bool is_ok = footprint->BuildPolyCourtyard();
1165 
1166  if( !is_ok && m_doFootprintOverlapping )
1167  {
1168  msg.Printf( _( "footprint \"%s\" has malformed courtyard" ),
1169  footprint->GetReference().GetData() );
1170  m_currentMarker = fillMarker( footprint->GetPosition(),
1172  msg, m_currentMarker );
1174  m_currentMarker = nullptr;
1175  success = false;
1176  }
1177 
1178  if( !m_doNoCourtyardDefined )
1179  continue;
1180 
1181  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 &&
1182  footprint->GetPolyCourtyardBack().OutlineCount() == 0 &&
1183  is_ok )
1184  {
1185  msg.Printf( _( "footprint \"%s\" has no courtyard defined" ),
1186  footprint->GetReference().GetData() );
1187  m_currentMarker = fillMarker( footprint->GetPosition(),
1189  msg, m_currentMarker );
1191  m_currentMarker = nullptr;
1192  success = false;
1193  }
1194  }
1195 
1197  return success;
1198 
1199  // Now test for overlapping on top layer:
1200  SHAPE_POLY_SET courtyard; // temporary storage of the courtyard of current footprint
1201 
1202  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1203  {
1204  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 )
1205  continue; // No courtyard defined
1206 
1207  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1208  {
1209  if( candidate->GetPolyCourtyardFront().OutlineCount() == 0 )
1210  continue; // No courtyard defined
1211 
1212  courtyard.RemoveAllContours();
1213  courtyard.Append( footprint->GetPolyCourtyardFront() );
1214 
1215  // Build the common area between footprint and the candidate:
1216  courtyard.BooleanIntersection( candidate->GetPolyCourtyardFront(),
1218 
1219  // If no overlap, courtyard is empty (no common area).
1220  // Therefore if a common polygon exists, this is a DRC error
1221  if( courtyard.OutlineCount() )
1222  {
1223  //Overlap between footprint and candidate
1224  msg.Printf( _( "footprints \"%s\" and \"%s\" overlap on front (top) layer" ),
1225  footprint->GetReference().GetData(),
1226  candidate->GetReference().GetData() );
1227  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1228  wxPoint loc( pos.x, pos.y );
1230  m_currentMarker );
1232  m_currentMarker = nullptr;
1233  success = false;
1234  }
1235  }
1236  }
1237 
1238  // Test for overlapping on bottom layer:
1239  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1240  {
1241  if( footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
1242  continue; // No courtyard defined
1243 
1244  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1245  {
1246  if( candidate->GetPolyCourtyardBack().OutlineCount() == 0 )
1247  continue; // No courtyard defined
1248 
1249  courtyard.RemoveAllContours();
1250  courtyard.Append( footprint->GetPolyCourtyardBack() );
1251 
1252  // Build the common area between footprint and the candidate:
1253  courtyard.BooleanIntersection( candidate->GetPolyCourtyardBack(),
1255 
1256  // If no overlap, courtyard is empty (no common area).
1257  // Therefore if a common polygon exists, this is a DRC error
1258  if( courtyard.OutlineCount() )
1259  {
1260  //Overlap between footprint and candidate
1261  msg.Printf( _( "footprints \"%s\" and \"%s\" overlap on back (bottom) layer" ),
1262  footprint->GetReference().GetData(),
1263  candidate->GetReference().GetData() );
1264  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1265  wxPoint loc( pos.x, pos.y );
1267  m_currentMarker );
1269  m_currentMarker = nullptr;
1270  success = false;
1271  }
1272  }
1273  }
1274 
1275  return success;
1276 }
bool m_doNoCourtyardDefined
Definition: drc.h:175
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
MODULE * Next() const
Definition: class_module.h:121
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:89
#define DRCE_MISSING_COURTYARD_IN_FOOTPRINT
footprint has no courtyard defined
Definition: drc.h:88
BOARD * m_pcb
Definition: drc.h:210
bool m_doFootprintOverlapping
Definition: drc.h:174
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:98
Class SHAPE_POLY_SET.
#define DRCE_OVERLAPPING_FOOTPRINTS
footprint courtyards overlap
Definition: drc.h:87
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp ...
MARKER_PCB * m_currentMarker
Definition: drc.h:181
DLIST< MODULE > m_Modules
Definition: class_board.h:245
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 511 of file drc.cpp.

References addMarkerToPcb(), DRCE_NETCLASS_CLEARANCE, DRCE_NETCLASS_TRACKWIDTH, DRCE_NETCLASS_uVIADRILLSIZE, DRCE_NETCLASS_uVIASIZE, DRCE_NETCLASS_VIADRILLSIZE, DRCE_NETCLASS_VIASIZE, fillMarker(), 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, and BOARD_DESIGN_SETTINGS::m_ViasMinSize.

Referenced by testNetClasses().

512 {
513  bool ret = true;
514 
516 
517 #define FmtVal( x ) GetChars( StringFromValue( g_UserUnit, x ) )
518 
519 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
520  if( nc->GetClearance() < g.m_MinClearance )
521  {
522  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
523  GetChars( nc->GetName() ),
524  FmtVal( nc->GetClearance() ),
525  FmtVal( g.m_TrackClearance )
526  );
527 
529  m_currentMarker = nullptr;
530  ret = false;
531  }
532 #endif
533 
534  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
535  {
536  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
537  GetChars( nc->GetName() ),
538  FmtVal( nc->GetTrackWidth() ),
540  );
541 
543  m_currentMarker = nullptr;
544  ret = false;
545  }
546 
547  if( nc->GetViaDiameter() < g.m_ViasMinSize )
548  {
549  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
550  GetChars( nc->GetName() ),
551  FmtVal( nc->GetViaDiameter() ),
552  FmtVal( g.m_ViasMinSize )
553  );
554 
556  m_currentMarker = nullptr;
557  ret = false;
558  }
559 
560  if( nc->GetViaDrill() < g.m_ViasMinDrill )
561  {
562  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
563  GetChars( nc->GetName() ),
564  FmtVal( nc->GetViaDrill() ),
566  );
567 
569  m_currentMarker = nullptr;
570  ret = false;
571  }
572 
573  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
574  {
575  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
576  GetChars( nc->GetName() ),
577  FmtVal( nc->GetuViaDiameter() ),
579  );
580 
582  m_currentMarker = nullptr;
583  ret = false;
584  }
585 
586  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
587  {
588  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
589  GetChars( nc->GetName() ),
590  FmtVal( nc->GetuViaDrill() ),
592  );
593 
595  m_currentMarker = nullptr;
596  ret = false;
597  }
598 
599  return ret;
600 }
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
#define DRCE_NETCLASS_TRACKWIDTH
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc.h:75
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:76
BOARD * m_pcb
Definition: drc.h:210
#define DRCE_NETCLASS_uVIADRILLSIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc.h:80
#define DRCE_NETCLASS_VIASIZE
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc.h:77
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
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:532
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:78
int m_MicroViasMinSize
micro vias (not vias) min diameter
#define FmtVal(x)
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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:79
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
aRefPadThe pad to test
aStartThe start of the pad list to test against
aEndMarks the end of the list and is not included
x_limitis used to stop the test (when the any pad's X coord exceeds this)

Definition at line 1020 of file drc.cpp.

References LSET::AllCuMask(), checkClearancePadToPad(), DRCE_HOLE_NEAR_PAD, DRCE_PAD_NEAR_PAD1, fillMarker(), 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, 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(), D_PAD::SetSize(), and wxPoint::x.

Referenced by testPad2Pad().

1021 {
1022  const static LSET all_cu = LSET::AllCuMask();
1023 
1024  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1025 
1026  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1027  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1028  * Therefore, this dummy pad is a circle or an oval.
1029  * A pad must have a parent because some functions expect a non null parent
1030  * to find the parent board, and some other data
1031  */
1032  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1033  D_PAD dummypad( &dummymodule );
1034 
1035  // Ensure the hole is on all copper layers
1036  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1037 
1038  // Use the minimal local clearance value for the dummy pad.
1039  // The clearance of the active pad will be used as minimum distance to a hole
1040  // (a value = 0 means use netclass value)
1041  dummypad.SetLocalClearance( 1 );
1042 
1043  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1044  {
1045  D_PAD* pad = *pad_list;
1046 
1047  if( pad == aRefPad )
1048  continue;
1049 
1050  // We can stop the test when pad->GetPosition().x > x_limit
1051  // because the list is sorted by X values
1052  if( pad->GetPosition().x > x_limit )
1053  break;
1054 
1055  // No problem if pads which are on copper layers are on different copper layers,
1056  // (pads can be only on a technical layer, to build complex pads)
1057  // but their hole (if any ) can create DRC error because they are on all
1058  // copper layers, so we test them
1059  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1060  ( pad->GetLayerSet() & all_cu ) != 0 &&
1061  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1062  {
1063  // if holes are in the same location and have the same size and shape,
1064  // this can be accepted
1065  if( pad->GetPosition() == aRefPad->GetPosition()
1066  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1067  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1068  {
1069  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1070  continue;
1071 
1072  // for oval holes: must also have the same orientation
1073  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1074  continue;
1075  }
1076 
1077  /* Here, we must test clearance between holes and pads
1078  * dummy pad size and shape is adjusted to pad drill size and shape
1079  */
1080  if( pad->GetDrillSize().x )
1081  {
1082  // pad under testing has a hole, test this hole against pad reference
1083  dummypad.SetPosition( pad->GetPosition() );
1084  dummypad.SetSize( pad->GetDrillSize() );
1085  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1087  dummypad.SetOrientation( pad->GetOrientation() );
1088 
1089  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1090  {
1091  // here we have a drc error on pad!
1092  m_currentMarker = fillMarker( pad, aRefPad,
1094  return false;
1095  }
1096  }
1097 
1098  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1099  {
1100  dummypad.SetPosition( aRefPad->GetPosition() );
1101  dummypad.SetSize( aRefPad->GetDrillSize() );
1102  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1104  dummypad.SetOrientation( aRefPad->GetOrientation() );
1105 
1106  if( !checkClearancePadToPad( pad, &dummypad ) )
1107  {
1108  // here we have a drc error on aRefPad!
1109  m_currentMarker = fillMarker( aRefPad, pad,
1111  return false;
1112  }
1113  }
1114 
1115  continue;
1116  }
1117 
1118  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1119  // But no problem if pads have the same netcode (same net)
1120  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1121  continue;
1122 
1123  // if pads are from the same footprint
1124  if( pad->GetParent() == aRefPad->GetParent() )
1125  {
1126  // and have the same pad number ( equivalent pads )
1127 
1128  // one can argue that this 2nd test is not necessary, that any
1129  // two pads from a single module are acceptable. This 2nd test
1130  // should eventually be a configuration option.
1131  if( pad->PadNameEqual( aRefPad ) )
1132  continue;
1133  }
1134 
1135  // if either pad has no drill and is only on technical layers, not a clearance violation
1136  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1137  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1138  {
1139  continue;
1140  }
1141 
1142  if( !checkClearancePadToPad( aRefPad, pad ) )
1143  {
1144  // here we have a drc error!
1146  return false;
1147  }
1148  }
1149 
1150  return true;
1151 }
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:673
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:62
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc.h:68
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:210
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
int GetNetCode() const
Function GetNetCode.
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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 head of a list of tracks 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(), LSET::AllCuMask(), PNS::angle(), ArcTangente(), B_Cu, checkClearanceSegmToPad(), checkLine(), checkMarginToCircle(), delta, 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_PAD, DRCE_TRACK_NEAR_THROUGH_HOLE, DRCE_TRACK_NEAR_VIA, DRCE_TRACK_SEGMENTS_TOO_CLOSE, DRCE_TRACKS_CROSSING, DRCE_VIA_HOLE_BIGGER, DRCE_VIA_NEAR_TRACK, DRCE_VIA_NEAR_VIA, err, EuclideanNorm(), F_Cu, fillMarker(), 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(), D_PAD::GetPosition(), TRACK::GetStart(), VIA::GetViaType(), TRACK::GetWidth(), In1_Cu, VIA::LayerPair(), BOARD_DESIGN_SETTINGS::m_BlindBuriedViaAllowed, 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, TRACK::Next(), PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PCB_VIA_T, BOARD_COMMIT::Push(), RotatePoint(), D_PAD::SetLayerSet(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), D_PAD::SetSize(), D_PAD::ShapePos(), EDA_ITEM::Type(), VIA_BLIND_BURIED, VIA_MICROVIA, wxPoint::x, and wxPoint::y.

Referenced by Drc(), 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  BOARD_COMMIT commit( m_pcbEditorFrame );
151 
152  for( auto marker : markers )
153  commit.Add( marker );
154 
155  commit.Push( wxEmptyString, false, false );
156  };
157 
158  // Returns false if we should return false from call site, or true to continue
159  auto handleNewMarker = [&]() -> bool
160  {
162  {
163  if( markers.size() > 0 )
164  commitMarkers();
165 
166  return false;
167  }
168  else
169  return true;
170  };
171 
172  NETCLASSPTR netclass = aRefSeg->GetNetClass();
174 
175  /* In order to make some calculations more easier or faster,
176  * pads and tracks coordinates will be made relative to the reference segment origin
177  */
178  wxPoint origin = aRefSeg->GetStart(); // origin will be the origin of other coordinates
179 
180  m_segmEnd = delta = aRefSeg->GetEnd() - origin;
181  m_segmAngle = 0;
182 
183  layerMask = aRefSeg->GetLayerSet();
184  net_code_ref = aRefSeg->GetNetCode();
185 
186  // Phase 0 : Test vias
187  if( aRefSeg->Type() == PCB_VIA_T )
188  {
189  const VIA *refvia = static_cast<const VIA*>( aRefSeg );
190  // test if the via size is smaller than minimum
191  if( refvia->GetViaType() == VIA_MICROVIA )
192  {
193  if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
194  {
195  markers.push_back( fillMarker( refvia, nullptr,
196  DRCE_TOO_SMALL_MICROVIA, nullptr ) );
197  if( !handleNewMarker() )
198  return false;
199  }
200 
201  if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
202  {
203  markers.push_back( fillMarker( refvia, nullptr,
204  DRCE_TOO_SMALL_MICROVIA_DRILL, nullptr ) );
205  if( !handleNewMarker() )
206  return false;
207  }
208  }
209  else
210  {
211  if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
212  {
213  markers.push_back( fillMarker( refvia, nullptr,
214  DRCE_TOO_SMALL_VIA, nullptr ) );
215  if( !handleNewMarker() )
216  return false;
217  }
218 
219  if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
220  {
221  markers.push_back( fillMarker( refvia, nullptr,
222  DRCE_TOO_SMALL_VIA_DRILL, nullptr ) );
223  if( !handleNewMarker() )
224  return false;
225  }
226  }
227 
228  // test if via's hole is bigger than its diameter
229  // This test is necessary since the via hole size and width can be modified
230  // and a default via hole can be bigger than some vias sizes
231  if( refvia->GetDrillValue() > refvia->GetWidth() )
232  {
233  markers.push_back( fillMarker( refvia, nullptr,
234  DRCE_VIA_HOLE_BIGGER, nullptr ) );
235  if( !handleNewMarker() )
236  return false;
237  }
238 
239  // test if the type of via is allowed due to design rules
240  if( ( refvia->GetViaType() == VIA_MICROVIA ) &&
241  ( m_pcb->GetDesignSettings().m_MicroViasAllowed == false ) )
242  {
243  markers.push_back( fillMarker( refvia, nullptr,
244  DRCE_MICRO_VIA_NOT_ALLOWED, nullptr ) );
245  if( !handleNewMarker() )
246  return false;
247  }
248 
249  // test if the type of via is allowed due to design rules
250  if( ( refvia->GetViaType() == VIA_BLIND_BURIED ) &&
252  {
253  markers.push_back( fillMarker( refvia, nullptr,
254  DRCE_BURIED_VIA_NOT_ALLOWED, nullptr ) );
255  if( !handleNewMarker() )
256  return false;
257  }
258 
259  // For microvias: test if they are blind vias and only between 2 layers
260  // because they are used for very small drill size and are drill by laser
261  // and **only one layer** can be drilled
262  if( refvia->GetViaType() == VIA_MICROVIA )
263  {
264  PCB_LAYER_ID layer1, layer2;
265  bool err = true;
266 
267  refvia->LayerPair( &layer1, &layer2 );
268 
269  if( layer1 > layer2 )
270  std::swap( layer1, layer2 );
271 
272  if( layer2 == B_Cu && layer1 == m_pcb->GetDesignSettings().GetCopperLayerCount() - 2 )
273  err = false;
274  else if( layer1 == F_Cu && layer2 == In1_Cu )
275  err = false;
276 
277  if( err )
278  {
279  markers.push_back( fillMarker( refvia, nullptr,
281  if( !handleNewMarker() )
282  return false;
283  }
284  }
285 
286  }
287  else // This is a track segment
288  {
289  if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth )
290  {
291  markers.push_back( fillMarker( aRefSeg, nullptr,
292  DRCE_TOO_SMALL_TRACK_WIDTH, nullptr ) );
293  if( !handleNewMarker() )
294  return false;
295  }
296  }
297 
298  // for a non horizontal or vertical segment Compute the segment angle
299  // in tenths of degrees and its length
300  if( delta.x || delta.y )
301  {
302  // Compute the segment angle in 0,1 degrees
303  m_segmAngle = ArcTangente( delta.y, delta.x );
304 
305  // Compute the segment length: we build an equivalent rotated segment,
306  // this segment is horizontal, therefore dx = length
307  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
308  }
309 
310  m_segmLength = delta.x;
311 
312  /******************************************/
313  /* Phase 1 : test DRC track to pads : */
314  /******************************************/
315 
316  /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
317  * but having a hole
318  * This dummy pad has the size and shape of the hole
319  * to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
320  * Therefore, this dummy pad is a circle or an oval.
321  * A pad must have a parent because some functions expect a non null parent
322  * to find the parent board, and some other data
323  */
324  MODULE dummymodule( m_pcb ); // Creates a dummy parent
325  D_PAD dummypad( &dummymodule );
326 
327  dummypad.SetLayerSet( LSET::AllCuMask() ); // Ensure the hole is on all layers
328 
329  // Compute the min distance to pads
330  if( testPads )
331  {
332  unsigned pad_count = m_pcb->GetPadCount();
333 
334  auto pads = m_pcb->GetPads();
335 
336  for( unsigned ii = 0; ii < pad_count; ++ii )
337  {
338  D_PAD* pad = pads[ii];
339 
340  /* No problem if pads are on another layer,
341  * But if a drill hole exists (a pad on a single layer can have a hole!)
342  * we must test the hole
343  */
344  if( !( pad->GetLayerSet() & layerMask ).any() )
345  {
346  /* We must test the pad hole. In order to use the function
347  * checkClearanceSegmToPad(),a pseudo pad is used, with a shape and a
348  * size like the hole
349  */
350  if( pad->GetDrillSize().x == 0 )
351  continue;
352 
353  dummypad.SetSize( pad->GetDrillSize() );
354  dummypad.SetPosition( pad->GetPosition() );
355  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
357  dummypad.SetOrientation( pad->GetOrientation() );
358 
359  m_padToTestPos = dummypad.GetPosition() - origin;
360 
361  if( !checkClearanceSegmToPad( &dummypad, aRefSeg->GetWidth(),
362  netclass->GetClearance() ) )
363  {
364  markers.push_back( fillMarker( aRefSeg, pad,
365  DRCE_TRACK_NEAR_THROUGH_HOLE, nullptr ) );
366  if( !handleNewMarker() )
367  return false;
368  }
369 
370  continue;
371  }
372 
373  // The pad must be in a net (i.e pt_pad->GetNet() != 0 )
374  // but no problem if the pad netcode is the current netcode (same net)
375  if( pad->GetNetCode() // the pad must be connected
376  && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok
377  continue;
378 
379  // DRC for the pad
380  shape_pos = pad->ShapePos();
381  m_padToTestPos = shape_pos - origin;
382 
383  if( !checkClearanceSegmToPad( pad, aRefSeg->GetWidth(),
384  aRefSeg->GetClearance( pad ) ) )
385  {
386  markers.push_back( fillMarker( aRefSeg, pad,
387  DRCE_TRACK_NEAR_PAD, nullptr ) );
388  if( !handleNewMarker() )
389  return false;
390  }
391  }
392  }
393 
394  /***********************************************/
395  /* Phase 2: test DRC with other track segments */
396  /***********************************************/
397 
398  // At this point the reference segment is the X axis
399 
400  // Test the reference segment with other track segments
401  wxPoint segStartPoint;
402  wxPoint segEndPoint;
403 
404  for( track = aStart; track; track = track->Next() )
405  {
406  // No problem if segments have the same net code:
407  if( net_code_ref == track->GetNetCode() )
408  continue;
409 
410  // No problem if segment are on different layers :
411  if( !( layerMask & track->GetLayerSet() ).any() )
412  continue;
413 
414  // the minimum distance = clearance plus half the reference track
415  // width plus half the other track's width
416  int w_dist = aRefSeg->GetClearance( track );
417  w_dist += ( aRefSeg->GetWidth() + track->GetWidth() ) / 2;
418 
419  // Due to many double to int conversions during calculations, which
420  // create rounding issues,
421  // the exact clearance margin cannot be really known.
422  // To avoid false bad DRC detection due to these rounding issues,
423  // slightly decrease the w_dist (remove one nanometer is enough !)
424  w_dist -= 1;
425 
426  // If the reference segment is a via, we test it here
427  if( aRefSeg->Type() == PCB_VIA_T )
428  {
429  delta = track->GetEnd() - track->GetStart();
430  segStartPoint = aRefSeg->GetStart() - track->GetStart();
431 
432  if( track->Type() == PCB_VIA_T )
433  {
434  // Test distance between two vias, i.e. two circles, trivial case
435  if( EuclideanNorm( segStartPoint ) < w_dist )
436  {
437  markers.push_back( fillMarker( aRefSeg, track,
438  DRCE_VIA_NEAR_VIA, nullptr ) );
439  if( !handleNewMarker() )
440  return false;
441  }
442  }
443  else // test via to segment
444  {
445  // Compute l'angle du segment a tester;
446  double angle = ArcTangente( delta.y, delta.x );
447 
448  // Compute new coordinates ( the segment become horizontal)
449  RotatePoint( &delta, angle );
450  RotatePoint( &segStartPoint, angle );
451 
452  if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
453  {
454  markers.push_back( fillMarker( track, aRefSeg,
455  DRCE_VIA_NEAR_TRACK, nullptr ) );
456  if( !handleNewMarker() )
457  return false;
458  }
459  }
460 
461  continue;
462  }
463 
464  /* We compute segStartPoint, segEndPoint = starting and ending point coordinates for
465  * the segment to test in the new axis : the new X axis is the
466  * reference segment. We must translate and rotate the segment to test
467  */
468  segStartPoint = track->GetStart() - origin;
469  segEndPoint = track->GetEnd() - origin;
470  RotatePoint( &segStartPoint, m_segmAngle );
471  RotatePoint( &segEndPoint, m_segmAngle );
472 
473  if( track->Type() == PCB_VIA_T )
474  {
475  if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
476  continue;
477 
478  markers.push_back( fillMarker( aRefSeg, track,
479  DRCE_TRACK_NEAR_VIA, nullptr ) );
480  if( !handleNewMarker() )
481  return false;
482  }
483 
484  /* We have changed axis:
485  * the reference segment is Horizontal.
486  * 3 cases : the segment to test can be parallel, perpendicular or have another direction
487  */
488  if( segStartPoint.y == segEndPoint.y ) // parallel segments
489  {
490  if( abs( segStartPoint.y ) >= w_dist )
491  continue;
492 
493  // Ensure segStartPoint.x <= segEndPoint.x
494  if( segStartPoint.x > segEndPoint.x )
495  std::swap( segStartPoint.x, segEndPoint.x );
496 
497  if( segStartPoint.x > ( -w_dist ) && segStartPoint.x < ( m_segmLength + w_dist ) )
498  {
499  // the start point is inside the reference range
500  // X........
501  // O--REF--+
502 
503  // Fine test : we consider the rounded shape of each end of the track segment:
504  if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
505  {
506  markers.push_back( fillMarker( aRefSeg, track,
507  DRCE_TRACK_ENDS1, nullptr ) );
508  if( !handleNewMarker() )
509  return false;
510  }
511 
512  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
513  {
514  markers.push_back( fillMarker( aRefSeg, track,
515  DRCE_TRACK_ENDS2, nullptr ) );
516  if( !handleNewMarker() )
517  return false;
518  }
519  }
520 
521  if( segEndPoint.x > ( -w_dist ) && segEndPoint.x < ( m_segmLength + w_dist ) )
522  {
523  // the end point is inside the reference range
524  // .....X
525  // O--REF--+
526  // Fine test : we consider the rounded shape of the ends
527  if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
528  {
529  markers.push_back( fillMarker( aRefSeg, track,
530  DRCE_TRACK_ENDS3, nullptr ) );
531  if( !handleNewMarker() )
532  return false;
533  }
534 
535  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
536  {
537  markers.push_back( fillMarker( aRefSeg, track,
538  DRCE_TRACK_ENDS4, nullptr ) );
539  if( !handleNewMarker() )
540  return false;
541  }
542  }
543 
544  if( segStartPoint.x <= 0 && segEndPoint.x >= 0 )
545  {
546  // the segment straddles the reference range (this actually only
547  // checks if it straddles the origin, because the other cases where already
548  // handled)
549  // X.............X
550  // O--REF--+
551  markers.push_back( fillMarker( aRefSeg, track,
552  DRCE_TRACK_SEGMENTS_TOO_CLOSE, nullptr ) );
553  if( !handleNewMarker() )
554  return false;
555  }
556  }
557  else if( segStartPoint.x == segEndPoint.x ) // perpendicular segments
558  {
559  if( ( segStartPoint.x <= ( -w_dist ) ) || ( segStartPoint.x >= ( m_segmLength + w_dist ) ) )
560  continue;
561 
562  // Test if segments are crossing
563  if( segStartPoint.y > segEndPoint.y )
564  std::swap( segStartPoint.y, segEndPoint.y );
565 
566  if( ( segStartPoint.y < 0 ) && ( segEndPoint.y > 0 ) )
567  {
568  markers.push_back( fillMarker( aRefSeg, track,
569  DRCE_TRACKS_CROSSING, nullptr ) );
570  if( !handleNewMarker() )
571  return false;
572  }
573 
574  // At this point the drc error is due to an end near a reference segm end
575  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
576  {
577  markers.push_back( fillMarker( aRefSeg, track,
578  DRCE_ENDS_PROBLEM1, nullptr ) );
579  if( !handleNewMarker() )
580  return false;
581  }
582  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
583  {
584  markers.push_back( fillMarker( aRefSeg, track,
585  DRCE_ENDS_PROBLEM2, nullptr ) );
586  if( !handleNewMarker() )
587  return false;
588  }
589  }
590  else // segments quelconques entre eux
591  {
592  // calcul de la "surface de securite du segment de reference
593  // First rought 'and fast) test : the track segment is like a rectangle
594 
595  m_xcliplo = m_ycliplo = -w_dist;
596  m_xcliphi = m_segmLength + w_dist;
597  m_ycliphi = w_dist;
598 
599  // A fine test is needed because a serment is not exactly a
600  // rectangle, it has rounded ends
601  if( !checkLine( segStartPoint, segEndPoint ) )
602  {
603  /* 2eme passe : the track has rounded ends.
604  * we must a fine test for each rounded end and the
605  * rectangular zone
606  */
607 
608  m_xcliplo = 0;
610 
611  if( !checkLine( segStartPoint, segEndPoint ) )
612  {
613  markers.push_back( fillMarker( aRefSeg, track,
614  DRCE_ENDS_PROBLEM3, nullptr ) );
615  if( !handleNewMarker() )
616  return false;
617  }
618  else // The drc error is due to the starting or the ending point of the reference segment
619  {
620  // Test the starting and the ending point
621  segStartPoint = track->GetStart();
622  segEndPoint = track->GetEnd();
623  delta = segEndPoint - segStartPoint;
624 
625  // Compute the segment orientation (angle) en 0,1 degre
626  double angle = ArcTangente( delta.y, delta.x );
627 
628  // Compute the segment length: delta.x = length after rotation
629  RotatePoint( &delta, angle );
630 
631  /* Comute the reference segment coordinates relatives to a
632  * X axis = current tested segment
633  */
634  wxPoint relStartPos = aRefSeg->GetStart() - segStartPoint;
635  wxPoint relEndPos = aRefSeg->GetEnd() - segStartPoint;
636 
637  RotatePoint( &relStartPos, angle );
638  RotatePoint( &relEndPos, angle );
639 
640  if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
641  {
642  markers.push_back( fillMarker( aRefSeg, track,
643  DRCE_ENDS_PROBLEM4, nullptr ) );
644  if( !handleNewMarker() )
645  return false;
646  }
647 
648  if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
649  {
650  markers.push_back( fillMarker( aRefSeg, track,
651  DRCE_ENDS_PROBLEM5, nullptr ) );
652  if( !handleNewMarker() )
653  return false;
654  }
655  }
656  }
657  }
658  }
659 
660  if( markers.size() > 0 )
661  {
662  commitMarkers();
663  return false;
664  }
665  else
666  return true;
667 }
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:673
#define DRCE_TOO_SMALL_MICROVIA_DRILL
Too small micro via drill.
Definition: drc.h:74
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
#define DRCE_TOO_SMALL_VIA
Too small via size.
Definition: drc.h:71
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
int m_ycliplo
Definition: drc.h:205
#define DRCE_TRACK_ENDS4
2 parallel track segments too close: fine end point test
Definition: drc.h:54
int m_ycliphi
Definition: drc.h:207
#define DRCE_TRACK_NEAR_PAD
pad too close to track
Definition: drc.h:47
int m_segmLength
Definition: drc.h:199
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:190
#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:119
#define DRCE_TRACK_ENDS2
2 parallel track segments too close: fine start point test
Definition: drc.h:52
#define DRCE_TRACK_SEGMENTS_TOO_CLOSE
2 parallel track segments too close: segm ends between segref ends
Definition: drc.h:55
#define DRCE_BURIED_VIA_NOT_ALLOWED
buried vias are not allowed
Definition: drc.h:92
#define DRCE_TRACK_NEAR_VIA
track too close to via
Definition: drc.h:48
BOARD * m_pcb
Definition: drc.h:210
#define DRCE_TOO_SMALL_MICROVIA
Too small micro via size.
Definition: drc.h:72
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:63
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
VIATYPE_T GetViaType() const
Definition: class_track.h:455
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:170
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:64
const wxPoint & GetStart() const
Definition: class_track.h:122
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:51
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:53
#define DRCE_ENDS_PROBLEM2
track ends are too close
Definition: drc.h:58
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_ENDS_PROBLEM3
track ends are too close
Definition: drc.h:59
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Check the distance from a point to a segment.
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
bool m_reportAllTrackErrors
Definition: drc.h:177
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc.h:206
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:209
string & err
Definition: json11.cpp:598
unsigned GetPadCount() const
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:60
int GetNetCode() const
Function GetNetCode.
#define DRCE_VIA_NEAR_VIA
via too close to via
Definition: drc.h:49
#define DRCE_TRACKS_CROSSING
tracks are crossing
Definition: drc.h:56
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:61
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
wxPoint m_segmEnd
Definition: drc.h:191
TRACK * Next() const
Definition: class_track.h:99
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:116
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:50
wxPoint ShapePos() const
Definition: class_pad.cpp:500
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
bool m_MicroViasAllowed
true to allow micro vias
#define DRCE_MICRO_VIA_NOT_ALLOWED
micro vias are not allowed
Definition: drc.h:91
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
const wxPoint GetPosition() const override
Definition: class_pad.h:220
int m_xcliplo
Definition: drc.h:204
#define DRCE_ENDS_PROBLEM1
track ends are too close
Definition: drc.h:57
#define DRCE_TOO_SMALL_VIA_DRILL
Too small via drill.
Definition: drc.h:73
#define DRCE_TRACK_NEAR_THROUGH_HOLE
thru hole is too close to track
Definition: drc.h:46
double m_segmAngle
Definition: drc.h:198
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
#define DRCE_TOO_SMALL_TRACK_WIDTH
Too small track width.
Definition: drc.h:70
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 971 of file drc.cpp.

References ZONE_CONTAINER::CommonLayerExists(), SHAPE_POLY_SET::Distance(), DRCE_TRACK_INSIDE_KEEPOUT, DRCE_VIA_INSIDE_KEEPOUT, fillMarker(), 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, ZONE_CONTAINER::Outline(), PCB_TRACE_T, PCB_VIA_T, and EDA_ITEM::Type().

Referenced by Drc().

972 {
973  // Test keepout areas for vias, tracks and pads inside keepout areas
974  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
975  {
976  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
977 
978  if( !area->GetIsKeepout() )
979  continue;
980 
981  if( aRefSeg->Type() == PCB_TRACE_T )
982  {
983  if( !area->GetDoNotAllowTracks() )
984  continue;
985 
986  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
987  continue;
988 
989  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
990  aRefSeg->GetWidth() ) == 0 )
991  {
992  m_currentMarker = fillMarker( aRefSeg, NULL,
994  return false;
995  }
996  }
997  else if( aRefSeg->Type() == PCB_VIA_T )
998  {
999  if( !area->GetDoNotAllowVias() )
1000  continue;
1001 
1002  auto viaLayers = aRefSeg->GetLayerSet();
1003 
1004  if( !area->CommonLayerExists( viaLayers ) )
1005  continue;
1006 
1007  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1008  {
1009  m_currentMarker = fillMarker( aRefSeg, NULL,
1011  return false;
1012  }
1013  }
1014  }
1015 
1016  return true;
1017 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
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
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
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:236
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:81
const wxPoint & GetEnd() const
Definition: class_track.h:119
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:210
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:602
const wxPoint GetPosition() const override
Definition: class_track.h:113
const wxPoint & GetStart() const
Definition: class_track.h:122
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
MARKER_PCB * m_currentMarker
Definition: drc.h:181
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:605
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
bool GetDoNotAllowVias() const
Definition: class_zone.h:604
int GetWidth() const
Definition: class_track.h:116
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:82
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
int DRC::Drc ( 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.

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

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

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

164 {
165  updatePointers();
166 
167  if( !doTrackDrc( aRefSegm, aList, true ) )
168  {
169  if( m_currentMarker )
171 
172  return BAD_DRC;
173  }
174 
175  if( !doTrackKeepoutDrc( aRefSegm ) )
176  {
177  wxASSERT( m_currentMarker );
178 
180  return BAD_DRC;
181  }
182 
183  return OK_DRC;
184 }
#define OK_DRC
Definition: drc.h:35
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:971
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:832
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:496
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
#define BAD_DRC
Definition: drc.h:36
MARKER_PCB * m_currentMarker
Definition: drc.h:181
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
int DRC::Drc ( 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

Parameters
aAreaThe areaparent 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 348 of file drc.cpp.

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

349 {
350  updatePointers();
351 
352  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
353  {
354  wxASSERT( m_currentMarker );
356  return BAD_DRC;
357  }
358 
359  return OK_DRC;
360 }
#define OK_DRC
Definition: drc.h:35
void SetMsgPanel(const std::vector< MSG_PANEL_ITEM > &aList)
Function SetMsgPanel clears the message panel and populates it with the contents of aList...
Definition: draw_frame.cpp:832
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:496
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
#define BAD_DRC
Definition: drc.h:36
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:181
int DRC::DrcBlind ( TRACK aRefSeg,
TRACK aList 
)
inline

Test the current segment and returns the result.

Any error is not displayed in the status panel.

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

References BAD_DRC, and OK_DRC.

450  {
451  updatePointers();
452 
453  if( ! doTrackDrc( aRefSeg, aList ) )
454  return BAD_DRC;
455 
456  return doTrackKeepoutDrc( aRefSeg ) ? OK_DRC : BAD_DRC;
457  }
#define OK_DRC
Definition: drc.h:35
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:971
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:496
#define BAD_DRC
Definition: drc.h:36
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
MARKER_PCB * DRC::fillMarker ( const TRACK aTrack,
BOARD_ITEM aItem,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Creates a marker and fills it in with information but does not add it to the BOARD.

Use this to report any kind of DRC problem or unconnected pad problem.

Parameters
aTrackThe reference track.
aItemAnother item on the BOARD, such as a VIA, SEGZONE, or TRACK.
aErrorCodeA categorizing identifier for the particular type of error that is being reported.
fillMeA MARKER_PCB* which is to be filled in, or NULL if one is to first be allocated, then filled.

Definition at line 49 of file drc_marker_functions.cpp.

References TRACK::GetEnd(), GetLineLength(), TRACK::GetPosition(), TRACK::GetSelectMenuText(), EDA_ITEM::GetSelectMenuText(), TRACK::GetStart(), PCB_PAD_T, PCB_TEXT_T, PCB_TRACE_T, PCB_VIA_T, MARKER_BASE::SetData(), MARKER_PCB::SetItem(), and EDA_ITEM::Type().

Referenced by doEdgeZoneDrc(), doFootprintOverlappingDrc(), doNetClass(), doPadToPadsDrc(), doTrackDrc(), doTrackKeepoutDrc(), testKeepoutAreas(), testTexts(), and testZones().

51 {
52  wxString textA = aTrack->GetSelectMenuText();
53  wxString textB;
54 
55  wxPoint position;
56  wxPoint posB;
57 
58  if( aItem ) // aItem might be NULL
59  {
60  textB = aItem->GetSelectMenuText();
61 
62  if( aItem->Type() == PCB_PAD_T )
63  {
64  posB = position = ((D_PAD*)aItem)->GetPosition();
65  }
66  else if( aItem->Type() == PCB_VIA_T )
67  {
68  posB = position = ((VIA*)aItem)->GetPosition();
69  }
70  else if( aItem->Type() == PCB_TRACE_T )
71  {
72  TRACK* track = (TRACK*) aItem;
73 
74  posB = track->GetPosition();
75 
76  wxPoint endPos = track->GetEnd();
77 
78  // either of aItem's start or end will be used for the marker position
79  // first assume start, then switch at end if needed. decision made on
80  // distance from end of aTrack.
81  position = track->GetStart();
82 
83  double dToEnd = GetLineLength( endPos, aTrack->GetEnd() );
84  double dToStart = GetLineLength( position, aTrack->GetEnd() );
85 
86  if( dToEnd < dToStart )
87  position = endPos;
88  }
89  else if( aItem->Type() == PCB_TEXT_T )
90  {
91  position = aTrack->GetPosition();
92  posB = ((TEXTE_PCB*) aItem)->GetPosition();
93  }
94  }
95  else
96  position = aTrack->GetPosition();
97 
98  if( fillMe )
99  {
100  if( aItem )
101  fillMe->SetData( aErrorCode, position,
102  textA, aTrack->GetPosition(),
103  textB, posB );
104  else
105  fillMe->SetData( aErrorCode, position,
106  textA, aTrack->GetPosition() );
107  }
108  else
109  {
110  if( aItem )
111  {
112  fillMe = new MARKER_PCB( aErrorCode, position,
113  textA, aTrack->GetPosition(),
114  textB, posB );
115  fillMe->SetItem( aItem );
116  }
117  else
118  {
119  fillMe = new MARKER_PCB( aErrorCode, position,
120  textA, aTrack->GetPosition() );
121  }
122  }
123 
124  return fillMe;
125 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
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
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
virtual wxString GetSelectMenuText() const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
const wxPoint & GetEnd() const
Definition: class_track.h:119
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void SetItem(const BOARD_ITEM *aItem)
const wxPoint GetPosition() const override
Definition: class_track.h:113
const wxPoint & GetStart() const
Definition: class_track.h:122
virtual wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
MARKER_PCB * DRC::fillMarker ( D_PAD aPad,
BOARD_ITEM aItem,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Definition at line 128 of file drc_marker_functions.cpp.

References D_PAD::GetPosition(), EDA_ITEM::GetSelectMenuText(), D_PAD::GetSelectMenuText(), PCB_PAD_T, PCB_TEXT_T, MARKER_BASE::SetData(), MARKER_PCB::SetItem(), and EDA_ITEM::Type().

129 {
130  wxString textA = aPad->GetSelectMenuText();
131  wxString textB;
132 
133  wxPoint posA = aPad->GetPosition();
134  wxPoint posB;
135 
136  if( aItem )
137  {
138  textB = aItem->GetSelectMenuText();
139 
140  switch( aItem->Type() )
141  {
142  case PCB_PAD_T:
143  posB = ((D_PAD*)aItem)->GetPosition();
144  break;
145 
146  case PCB_TEXT_T:
147  posB = ((TEXTE_PCB*)aItem)->GetPosition();
148  break;
149 
150  default:
151  wxLogDebug( wxT("fillMarker: unsupported item") );
152  break;
153  }
154  }
155 
156  if( fillMe )
157  {
158  fillMe->SetData( aErrorCode, posA, textA, posA, textB, posB );
159  }
160  else
161  {
162  fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA, textB, posB );
163  fillMe->SetItem( aPad ); // TODO it has to be checked
164  }
165 
166  return fillMe;
167 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
Definition: class_pad.cpp:1182
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
virtual wxString GetSelectMenuText() const
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
void SetItem(const BOARD_ITEM *aItem)
const wxPoint GetPosition() const override
Definition: class_pad.h:220
MARKER_PCB * DRC::fillMarker ( ZONE_CONTAINER aArea,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Definition at line 170 of file drc_marker_functions.cpp.

References ZONE_CONTAINER::GetPosition(), ZONE_CONTAINER::GetSelectMenuText(), MARKER_BASE::SetData(), and MARKER_PCB::SetItem().

171 {
172  wxString textA = aArea->GetSelectMenuText();
173 
174  wxPoint posA = aArea->GetPosition();
175 
176  if( fillMe )
177  {
178  fillMe->SetData( aErrorCode, posA, textA, posA );
179  }
180  else
181  {
182  fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
183  fillMe->SetItem( aArea );
184  }
185 
186  return fillMe;
187 }
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
const wxPoint GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:169
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
void SetItem(const BOARD_ITEM *aItem)
MARKER_PCB * DRC::fillMarker ( const wxPoint aPos,
int  aErrorCode,
const wxString &  aMessage,
MARKER_PCB fillMe 
)
private

Definition at line 228 of file drc_marker_functions.cpp.

References MARKER_BASE::SetData().

229 {
230  wxPoint posA = aPos;
231 
232  if( fillMe )
233  fillMe->SetData( aErrorCode, posA, aMessage, posA );
234  else
235  fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
236 
237  return fillMe;
238 }
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
MARKER_PCB * DRC::fillMarker ( const ZONE_CONTAINER aArea,
const wxPoint aPos,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Create a marker and fills it in with information but do not add it to the BOARD.

Use this to report any kind of DRC problem, or unconnected pad problem.

Parameters
aAreaThe zone to test
aPosposition of error
aErrorCodeType of error
fillMeA MARKER_PCB* which is to be filled in, or NULL if one is to first be allocated, then filled.

Definition at line 190 of file drc_marker_functions.cpp.

References ZONE_CONTAINER::GetSelectMenuText(), MARKER_BASE::SetData(), and MARKER_PCB::SetItem().

194 {
195  wxString textA = aArea->GetSelectMenuText();
196 
197  wxPoint posA = aPos;
198 
199  if( fillMe )
200  {
201  fillMe->SetData( aErrorCode, posA, textA, posA );
202  }
203  else
204  {
205  fillMe = new MARKER_PCB( aErrorCode, posA, textA, posA );
206  fillMe->SetItem( aArea );
207  }
208 
209  return fillMe;
210 }
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
void SetItem(const BOARD_ITEM *aItem)
MARKER_PCB * DRC::fillMarker ( int  aErrorCode,
const wxString &  aMessage,
MARKER_PCB fillMe 
)
private

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

Definition at line 213 of file drc_marker_functions.cpp.

References MARKER_BASE::SetData(), and MARKER_BASE::SetShowNoCoordinate().

214 {
215  wxPoint posA; // not displayed
216 
217  if( fillMe )
218  fillMe->SetData( aErrorCode, posA, aMessage, posA );
219  else
220  fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
221 
222  fillMe->SetShowNoCoordinate();
223 
224  return fillMe;
225 }
void SetShowNoCoordinate()
Definition: marker_base.h:192
void SetData(int aErrorCode, const wxPoint &aMarkerPos, const wxString &aText, const wxPoint &aPos, const wxString &bText, const wxPoint &bPos)
Function SetData fills in all the reportable data associated with a MARKER.
MARKER_PCB* DRC::GetCurrentMarker ( )
inline
Returns
a pointer to the current marker (last created marker

Definition at line 544 of file drc.h.

Referenced by PCB_EDIT_FRAME::Other_Layer_Route().

545  {
546  return m_currentMarker;
547  }
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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 487 of file drc.cpp.

References testUnconnected(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick().

488 {
489  testUnconnected();
490 
491  // update the m_drcDialog listboxes
492  updatePointers();
493 }
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:496
void testUnconnected()
Definition: drc.cpp:725
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 363 of file drc.cpp.

References PCB_EDIT_FRAME::Check_All_Zones(), doFootprintOverlappingDrc(), PCB_EDIT_FRAME::Fill_All_Zones(), PCB_BASE_FRAME::GetBoard(), m_doFootprintOverlapping, m_doKeepoutTest, m_doNoCourtyardDefined, m_doPad2PadTest, m_doUnconnectedTest, m_pcb, m_pcbEditorFrame, m_refillZones, testKeepoutAreas(), testNetClasses(), testPad2Pad(), testTexts(), testTracks(), testUnconnected(), testZones(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnStartdrcClick().

364 {
365  // be sure m_pcb is the current board, not a old one
366  // ( the board can be reloaded )
368 
369  // someone should have cleared the two lists before calling this.
370 
371  if( !testNetClasses() )
372  {
373  // testing the netclasses is a special case because if the netclasses
374  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
375  // class (a NET) will cause its items such as tracks, vias, and pads
376  // to also fail. So quit after *all* netclass errors have been reported.
377  if( aMessages )
378  aMessages->AppendText( _( "Aborting\n" ) );
379 
380  // update the m_drcDialog listboxes
381  updatePointers();
382 
383  return;
384  }
385 
386  // test pad to pad clearances, nothing to do with tracks, vias or zones.
387  if( m_doPad2PadTest )
388  {
389  if( aMessages )
390  {
391  aMessages->AppendText( _( "Pad clearances...\n" ) );
392  wxSafeYield();
393  }
394 
395  testPad2Pad();
396  }
397 
398  // test track and via clearances to other tracks, pads, and vias
399  if( aMessages )
400  {
401  aMessages->AppendText( _( "Track clearances...\n" ) );
402  wxSafeYield();
403  }
404 
405  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
406 
407  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
408  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
409 
410  if( m_refillZones )
411  {
412  aMessages->AppendText( _( "Refilling all zones...\n" ) );
413  m_pcbEditorFrame->Fill_All_Zones( caller );
414  }
415  else
416  {
417  aMessages->AppendText( _( "Checking zone fills...\n" ) );
419  }
420 
421  // test zone clearances to other zones
422  if( aMessages )
423  {
424  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
425  wxSafeYield();
426  }
427 
428  testZones();
429 
430  // find and gather unconnected pads.
431  if( m_doUnconnectedTest )
432  {
433  if( aMessages )
434  {
435  aMessages->AppendText( _( "Unconnected pads...\n" ) );
436  aMessages->Refresh();
437  }
438 
439  testUnconnected();
440  }
441 
442  // find and gather vias, tracks, pads inside keepout areas.
443  if( m_doKeepoutTest )
444  {
445  if( aMessages )
446  {
447  aMessages->AppendText( _( "Keepout areas ...\n" ) );
448  aMessages->Refresh();
449  }
450 
452  }
453 
454  // find and gather vias, tracks, pads inside text boxes.
455  if( aMessages )
456  {
457  aMessages->AppendText( _( "Test texts...\n" ) );
458  wxSafeYield();
459  }
460 
461  testTexts();
462 
463  // find overlapping courtyard ares.
465  {
466  if( aMessages )
467  {
468  aMessages->AppendText( _( "Courtyard areas...\n" ) );
469  aMessages->Refresh();
470  }
471 
473  }
474 
475  // update the m_drcDialog listboxes
476  updatePointers();
477 
478  if( aMessages )
479  {
480  // no newline on this one because it is last, don't want the window
481  // to unnecessarily scroll.
482  aMessages->AppendText( _( "Finished" ) );
483  }
484 }
bool m_refillZones
Definition: drc.h:176
bool m_doNoCourtyardDefined
Definition: drc.h:175
void testKeepoutAreas()
Definition: drc.cpp:793
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 testTexts()
Definition: drc.cpp:847
BOARD * m_pcb
Definition: drc.h:210
bool m_doFootprintOverlapping
Definition: drc.h:174
bool m_doKeepoutTest
Definition: drc.h:172
void testZones()
Definition: drc.cpp:755
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:496
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
bool m_doPad2PadTest
Definition: drc.h:169
void testPad2Pad()
Definition: drc.cpp:626
bool doFootprintOverlappingDrc()
Test for footprint courtyard overlaps.
Definition: drc.cpp:1154
bool testNetClasses()
Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance ...
Definition: drc.cpp:603
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
Definition: drc.cpp:666
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:725
bool m_doUnconnectedTest
Definition: drc.h:170
void DRC::SetSettings ( bool  aPad2PadTest,
bool  aUnconnectedTest,
bool  aZonesTest,
bool  aKeepoutTest,
bool  aRefillZones,
bool  aCourtyardTest,
bool  aCourtyardMissingTest,
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.
aCourtyardTestTells whether to test footprint courtyard overlap.
aCourtyardMissingTestTells whether to test missing courtyard definition in footprint.
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 509 of file drc.h.

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

514  {
515  m_doPad2PadTest = aPad2PadTest;
516  m_doUnconnectedTest = aUnconnectedTest;
517  m_doZonesTest = aZonesTest;
518  m_doKeepoutTest = aKeepoutTest;
519  m_rptFilename = aReportName;
520  m_doCreateRptFile = aSaveReport;
521  m_doFootprintOverlapping = aCourtyardTest;
522  m_doNoCourtyardDefined = aCourtyardMissingTest;
523  m_refillZones = aRefillZones;
524  m_reportAllTrackErrors = aReportAllTrackErrors;
525  }
bool m_refillZones
Definition: drc.h:176
bool m_doNoCourtyardDefined
Definition: drc.h:175
bool m_doCreateRptFile
Definition: drc.h:173
bool m_doFootprintOverlapping
Definition: drc.h:174
bool m_doKeepoutTest
Definition: drc.h:172
bool m_doZonesTest
Definition: drc.h:171
bool m_reportAllTrackErrors
Definition: drc.h:177
bool m_doPad2PadTest
Definition: drc.h:169
wxString m_rptFilename
Definition: drc.h:179
bool m_doUnconnectedTest
Definition: drc.h:170
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 59 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().

60 {
61  bool show_dlg_modal = true;
62 
63  // the dialog needs a parent frame. if it is not specified, this is
64  // the PCB editor frame specified in DRC class.
65  if( aParent == NULL )
66  {
67  // if any parent is specified, the dialog is modal.
68  // if this is the default PCB editor frame, it is not modal
69  show_dlg_modal = false;
70  aParent = m_pcbEditorFrame;
71  }
72 
74  toolMgr->RunAction( ACTIONS::cancelInteractive, true );
75  toolMgr->DeactivateTool();
76  toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
77 
78  if( !m_drcDialog )
79  {
80  m_drcDialog = new DIALOG_DRC_CONTROL( this, m_pcbEditorFrame, aParent );
82 
84 
85  if( show_dlg_modal )
86  m_drcDialog->ShowModal();
87  else
88  m_drcDialog->Show( true );
89  }
90  else // The dialog is just not visible (because the user has double clicked on an error item)
91  {
93  m_drcDialog->Show( true );
94  }
95 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool m_doCreateRptFile
Definition: drc.h:173
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:211
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:496
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
bool Show(bool show) override
friend class DIALOG_DRC_CONTROL
Definition: drc.h:164
TOOL_MANAGER * GetToolManager() const
Function GetToolManager returns the tool manager instance, if any.
Definition: draw_frame.h:902
wxString m_rptFilename
Definition: drc.h:179
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:179
void DRC::testKeepoutAreas ( )
private

Definition at line 793 of file drc.cpp.

References addMarkerToPcb(), ZONE_CONTAINER::CommonLayerExists(), SHAPE_POLY_SET::Distance(), DRCE_TRACK_INSIDE_KEEPOUT, DRCE_VIA_INSIDE_KEEPOUT, fillMarker(), BOARD::GetArea(), BOARD::GetAreaCount(), ZONE_CONTAINER::GetDoNotAllowTracks(), ZONE_CONTAINER::GetDoNotAllowVias(), ZONE_CONTAINER::GetIsKeepout(), BOARD_ITEM::GetLayerSet(), ZONE_CONTAINER::IsOnLayer(), m_currentMarker, m_pcb, BOARD::m_Track, TRACK::Next(), ZONE_CONTAINER::Outline(), PCB_TRACE_T, and PCB_VIA_T.

Referenced by RunTests().

794 {
795  // Test keepout areas for vias, tracks and pads inside keepout areas
796  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
797  {
798  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
799 
800  if( !area->GetIsKeepout() )
801  {
802  continue;
803  }
804 
805  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
806  {
807  if( segm->Type() == PCB_TRACE_T )
808  {
809  if( !area->GetDoNotAllowTracks() )
810  continue;
811 
812  // Ignore if the keepout zone is not on the same layer
813  if( !area->IsOnLayer( segm->GetLayer() ) )
814  continue;
815 
816  if( area->Outline()->Distance( SEG( segm->GetStart(), segm->GetEnd() ),
817  segm->GetWidth() ) == 0 )
818  {
819  addMarkerToPcb( fillMarker( segm, NULL,
821  m_currentMarker = nullptr;
822  }
823  }
824  else if( segm->Type() == PCB_VIA_T )
825  {
826  if( ! area->GetDoNotAllowVias() )
827  continue;
828 
829  auto viaLayers = segm->GetLayerSet();
830 
831  if( !area->CommonLayerExists( viaLayers ) )
832  continue;
833 
834  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
835  {
836  addMarkerToPcb( fillMarker( segm, NULL,
838  m_currentMarker = nullptr;
839  }
840  }
841  }
842  // Test pads: TODO
843  }
844 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
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
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
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:236
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc.h:81
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc.h:210
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:602
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
MARKER_PCB * m_currentMarker
Definition: drc.h:181
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:605
TRACK * Next() const
Definition: class_track.h:99
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
bool GetDoNotAllowVias() const
Definition: class_zone.h:604
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:82
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
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 603 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().

604 {
605  bool ret = true;
606 
608 
609  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
610 
611  if( !doNetClass( netclasses.GetDefault(), msg ) )
612  ret = false;
613 
614  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
615  {
616  NETCLASSPTR nc = i->second;
617 
618  if( !doNetClass( nc, msg ) )
619  ret = false;
620  }
621 
622  return ret;
623 }
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
Definition: drc.cpp:511
iterator end()
Definition: netclass.h:256
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:258
BOARD * m_pcb
Definition: drc.h:210
iterator begin()
Definition: netclass.h:255
Class NETCLASSES is a container for NETCLASS instances.
Definition: netclass.h:231
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:275
size_t i
Definition: json11.cpp:597
NETCLASSES m_NetClasses
List of current netclasses. There is always the default netclass.
void DRC::testPad2Pad ( )
private

Definition at line 626 of file drc.cpp.

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

Referenced by RunTests().

627 {
628  std::vector<D_PAD*> sortedPads;
629 
630  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
631 
632  // find the max size of the pads (used to stop the test)
633  int max_size = 0;
634 
635  for( unsigned i = 0; i < sortedPads.size(); ++i )
636  {
637  D_PAD* pad = sortedPads[i];
638 
639  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
640  int radius = pad->GetBoundingRadius();
641 
642  if( radius > max_size )
643  max_size = radius;
644  }
645 
646  // Test the pads
647  D_PAD** listEnd = &sortedPads[ sortedPads.size() ];
648 
649  for( unsigned i = 0; i< sortedPads.size(); ++i )
650  {
651  D_PAD* pad = sortedPads[i];
652 
653  int x_limit = max_size + pad->GetClearance() +
654  pad->GetBoundingRadius() + pad->GetPosition().x;
655 
656  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
657  {
658  wxASSERT( m_currentMarker );
660  m_currentMarker = nullptr;
661  }
662  }
663 }
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:210
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:593
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:1020
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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:546
const wxPoint GetPosition() const override
Definition: class_pad.h:220
void DRC::testTexts ( )
private

Definition at line 847 of file drc.cpp.

References addMarkerToPcb(), ArcTangente(), checkClearanceSegmToPad(), delta, dist, BOARD::Drawings(), DRCE_PAD_INSIDE_TEXT, DRCE_TRACK_INSIDE_TEXT, DRCE_VIA_INSIDE_TEXT, fillMarker(), D_PAD::GetClearance(), BOARD::GetPads(), EDA_TEXT::GetThickness(), IsCopperLayer(), D_PAD::IsOnLayer(), m_currentMarker, m_padToTestPos, m_pcb, m_segmAngle, m_segmEnd, m_segmLength, BOARD::m_Track, TRACK::Next(), PCB_TEXT_T, PCB_TRACE_T, PCB_VIA_T, SEG::PointCloserThan(), RotatePoint(), D_PAD::ShapePos(), EDA_TEXT::TransformTextShapeToSegmentList(), wxPoint::x, and wxPoint::y.

Referenced by RunTests().

848 {
849  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
850  std::vector<D_PAD*> padList = m_pcb->GetPads();
851 
852  // Test text areas for vias, tracks and pads inside text areas
853  for( auto item : m_pcb->Drawings() )
854  {
855  // Drc test only items on copper layers
856  if( !IsCopperLayer( item->GetLayer() ) )
857  continue;
858 
859  // only texts on copper layers are tested
860  if( item->Type() != PCB_TEXT_T )
861  continue;
862 
863  textShape.clear();
864 
865  // So far the bounding box makes up the text-area
866  TEXTE_PCB* text = (TEXTE_PCB*) item;
867  text->TransformTextShapeToSegmentList( textShape );
868 
869  if( textShape.size() == 0 ) // Should not happen (empty text?)
870  continue;
871 
872  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
873  {
874  if( !track->IsOnLayer( item->GetLayer() ) )
875  continue;
876 
877  // Test the distance between each segment and the current track/via
878  int min_dist = ( track->GetWidth() + text->GetThickness() ) /2 +
879  track->GetClearance(NULL);
880 
881  if( track->Type() == PCB_TRACE_T )
882  {
883  SEG segref( track->GetStart(), track->GetEnd() );
884 
885  // Error condition: Distance between text segment and track segment is
886  // smaller than the clearance of the segment
887  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
888  {
889  SEG segtest( textShape[jj], textShape[jj+1] );
890  int dist = segref.Distance( segtest );
891 
892  if( dist < min_dist )
893  {
894  addMarkerToPcb( fillMarker( track, text,
896  m_currentMarker ) );
897  m_currentMarker = nullptr;
898  break;
899  }
900  }
901  }
902  else if( track->Type() == PCB_VIA_T )
903  {
904  // Error condition: Distance between text segment and via is
905  // smaller than the clearance of the via
906  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
907  {
908  SEG segtest( textShape[jj], textShape[jj+1] );
909 
910  if( segtest.PointCloserThan( track->GetPosition(), min_dist ) )
911  {
912  addMarkerToPcb( fillMarker( track, text,
914  m_currentMarker = nullptr;
915  break;
916  }
917  }
918  }
919  }
920 
921  // Test pads
922  for( unsigned ii = 0; ii < padList.size(); ii++ )
923  {
924  D_PAD* pad = padList[ii];
925 
926  if( !pad->IsOnLayer( item->GetLayer() ) )
927  continue;
928 
929  wxPoint shape_pos = pad->ShapePos();
930 
931  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
932  {
933  /* In order to make some calculations more easier or faster,
934  * pads and tracks coordinates will be made relative
935  * to the segment origin
936  */
937  wxPoint origin = textShape[jj]; // origin will be the origin of other coordinates
938  m_segmEnd = textShape[jj+1] - origin;
940  m_segmAngle = 0;
941 
942  // for a non horizontal or vertical segment Compute the segment angle
943  // in tenths of degrees and its length
944  if( delta.x || delta.y ) // delta.x == delta.y == 0 for vias
945  {
946  // Compute the segment angle in 0,1 degrees
947  m_segmAngle = ArcTangente( delta.y, delta.x );
948 
949  // Compute the segment length: we build an equivalent rotated segment,
950  // this segment is horizontal, therefore dx = length
951  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
952  }
953 
954  m_segmLength = delta.x;
955  m_padToTestPos = shape_pos - origin;
956 
957  if( !checkClearanceSegmToPad( pad, text->GetThickness(),
958  pad->GetClearance(NULL) ) )
959  {
960  addMarkerToPcb( fillMarker( pad, text,
962  m_currentMarker = nullptr;
963  break;
964  }
965  }
966  }
967  }
968 }
#define DRCE_TRACK_INSIDE_TEXT
Track in inside a text area.
Definition: drc.h:85
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
static const int dist[10][10]
Definition: dist.cpp:57
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
int m_segmLength
Definition: drc.h:199
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
wxPoint m_padToTestPos
Definition: drc.h:190
static const int delta[8][2]
Definition: solve.cpp:112
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:152
BOARD * m_pcb
Definition: drc.h:210
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:170
#define DRCE_VIA_INSIDE_TEXT
Via in inside a text area.
Definition: drc.h:84
#define DRCE_PAD_INSIDE_TEXT
Pad in inside a text area.
Definition: drc.h:86
MARKER_PCB * m_currentMarker
Definition: drc.h:181
Definition: seg.h:36
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Check the distance from a pad to segment.
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
wxPoint m_segmEnd
Definition: drc.h:191
TRACK * Next() const
Definition: class_track.h:99
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:479
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:546
wxPoint ShapePos() const
Definition: class_pad.cpp:500
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:644
double m_segmAngle
Definition: drc.h:198
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
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 666 of file drc.cpp.

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

Referenced by RunTests().

667 {
668  wxProgressDialog * progressDialog = NULL;
669  const int delta = 500; // This is the number of tests between 2 calls to the
670  // progress bar
671  int count = 0;
672 
673  for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
674  count++;
675 
676  int deltamax = count/delta;
677 
678  if( aShowProgressBar && deltamax > 3 )
679  {
680  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
681  // on OSX
682  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
683  deltamax, aActiveWindow,
684  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
685  progressDialog->Update( 0, wxEmptyString );
686  }
687 
688  int ii = 0;
689  count = 0;
690 
691  for( TRACK* segm = m_pcb->m_Track; segm; segm = segm->Next() )
692  {
693  if( ii++ > delta )
694  {
695  ii = 0;
696  count++;
697 
698  if( progressDialog )
699  {
700  if( !progressDialog->Update( count, wxEmptyString ) )
701  break; // Aborted by user
702 #ifdef __WXMAC__
703  // Work around a dialog z-order issue on OS X
704  if( count == deltamax )
705  aActiveWindow->Raise();
706 #endif
707  }
708  }
709 
710  if( !doTrackDrc( segm, segm->Next(), true ) )
711  {
712  if( m_currentMarker )
713  {
715  m_currentMarker = nullptr;
716  }
717  }
718  }
719 
720  if( progressDialog )
721  progressDialog->Destroy();
722 }
static const int delta[8][2]
Definition: solve.cpp:112
BOARD * m_pcb
Definition: drc.h:210
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
MARKER_PCB * m_currentMarker
Definition: drc.h:181
TRACK * Next() const
Definition: class_track.h:99
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Test the current segment.
DLIST< TRACK > m_Track
Definition: class_board.h:246
void DRC::testUnconnected ( )
private

Definition at line 725 of file drc.cpp.

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

Referenced by ListUnconnectedPads(), and RunTests().

726 {
727 
728  auto connectivity = m_pcb->GetConnectivity();
729 
730  connectivity->Clear();
731  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
732  connectivity->RecalculateRatsnest();
733 
734  std::vector<CN_EDGE> edges;
735  connectivity->GetUnconnectedEdges( edges );
736 
737  for( const auto& edge : edges )
738  {
739  wxString t_src = edge.GetSourceNode()->Parent()->GetSelectMenuText();
740  wxString t_dst = edge.GetTargetNode()->Parent()->GetSelectMenuText();
741  auto src = edge.GetSourcePos();
742  auto dst = edge.GetTargetPos();
743 
744 
745  DRC_ITEM* uncItem = new DRC_ITEM( DRCE_UNCONNECTED_ITEMS,
746  t_src,
747  t_dst,
748  wxPoint( src.x, src.y ), wxPoint( dst.x, dst.y ) );
749  m_unconnected.push_back( uncItem );
750 
751  }
752 }
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item. ...
Definition: drc_item.h:45
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc.h:45
BOARD * m_pcb
Definition: drc.h:210
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:213
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
void DRC::testZones ( )
private

Definition at line 755 of file drc.cpp.

References addMarkerToPcb(), DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE, fillMarker(), BOARD::GetArea(), BOARD::GetAreaCount(), BOARD::GetConnectivity(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::IsOnCopperLayer(), m_currentMarker, m_pcb, and TestZoneToZoneOutline().

Referenced by RunTests().

756 {
757  // Test copper areas for valid netcodes
758  // if a netcode is < 0 the netname was not found when reading a netlist
759  // if a netcode is == 0 the netname is void, and the zone is not connected.
760  // This is allowed, but i am not sure this is a good idea
761  //
762  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
763  // is stored, and initialized from the file or the zone properties editor.
764  // if it differs from the net name from net code, there is a DRC issue
765  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
766  {
767  ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
768 
769  if( !test_area->IsOnCopperLayer() )
770  continue;
771 
772  int netcode = test_area->GetNetCode();
773 
774  // a netcode < 0 or > 0 and no pad in net is a error or strange
775  // perhaps a "dead" net, which happens when all pads in this net were removed
776  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
777  int pads_in_net = (test_area->GetNetCode() > 0) ?
778  m_pcb->GetConnectivity()->GetPadCount( test_area->GetNetCode() ) : 1;
779 
780  if( ( netcode < 0 ) || pads_in_net == 0 )
781  {
782  addMarkerToPcb( fillMarker( test_area,
784  m_currentMarker = nullptr;
785  }
786  }
787 
788  // Test copper areas outlines, and create markers when needed
789  TestZoneToZoneOutline( NULL, true );
790 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Creates a marker and fills it in with information but does not add it to the BOARD.
int TestZoneToZoneOutline(ZONE_CONTAINER *aZone, bool aCreateMarkers)
Definition: drc.cpp:187
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:67
BOARD * m_pcb
Definition: drc.h:210
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc.h:181
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:982
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
int DRC::TestZoneToZoneOutline ( ZONE_CONTAINER aZone,
bool  aCreateMarkers 
)

Definition at line 187 of file drc.cpp.

References SEG::A, COMMIT::Add(), SEG::B, ZONE_CONTAINER::BuildSmoothedPoly(), SHAPE_POLY_SET::Contains(), COPPERAREA_CLOSE_TO_COPPERAREA, COPPERAREA_INSIDE_COPPERAREA, 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::GetSelectMenuText(), ZONE_CONTAINER::IsOnCopperLayer(), SHAPE_POLY_SET::IterateSegmentsWithHoles(), SHAPE_POLY_SET::IterateWithHoles(), m_pcbEditorFrame, BOARD_COMMIT::Push(), wxPoint::x, VECTOR2< T >::x, wxPoint::y, 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().

188 {
189  BOARD* board = m_pcbEditorFrame->GetBoard();
190  BOARD_COMMIT commit( m_pcbEditorFrame );
191  int nerrors = 0;
192 
193  // iterate through all areas
194  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
195  {
196  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
197  SHAPE_POLY_SET refSmoothedPoly;
198 
199  zoneRef->BuildSmoothedPoly( refSmoothedPoly );
200 
201  if( !zoneRef->IsOnCopperLayer() )
202  continue;
203 
204  // When testing only a single area, skip all others
205  if( aZone && ( aZone != zoneRef) )
206  continue;
207 
208  for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
209  {
210  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
211  SHAPE_POLY_SET testSmoothedPoly;
212 
213  zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
214 
215  if( zoneRef == zoneToTest )
216  continue;
217 
218  // test for same layer
219  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
220  continue;
221 
222  // Test for same net
223  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
224  continue;
225 
226  // test for different priorities
227  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
228  continue;
229 
230  // test for different types
231  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
232  continue;
233 
234  // Examine a candidate zone: compare zoneToTest to zoneRef
235 
236  // Get clearance used in zone to zone test. The policy used to
237  // obtain that value is now part of the zone object itself by way of
238  // ZONE_CONTAINER::GetClearance().
239  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
240 
241  // Keepout areas have no clearance, so set zone2zoneClearance to 1
242  // ( zone2zoneClearance = 0 can create problems in test functions)
243  if( zoneRef->GetIsKeepout() )
244  zone2zoneClearance = 1;
245 
246  // test for some corners of zoneRef inside zoneToTest
247  for( auto iterator = refSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
248  {
249  VECTOR2I currentVertex = *iterator;
250 
251  if( testSmoothedPoly.Contains( currentVertex ) )
252  {
253  // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
254  if( aCreateMarkers )
255  {
256  wxPoint pt( currentVertex.x, currentVertex.y );
257  wxString msg1 = zoneRef->GetSelectMenuText();
258  wxString msg2 = zoneToTest->GetSelectMenuText();
260  pt, msg1, pt, msg2, pt );
261  commit.Add( marker );
262  }
263 
264  nerrors++;
265  }
266  }
267 
268  // test for some corners of zoneToTest inside zoneRef
269  for( auto iterator = testSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
270  {
271  VECTOR2I currentVertex = *iterator;
272 
273  if( refSmoothedPoly.Contains( currentVertex ) )
274  {
275  // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
276  if( aCreateMarkers )
277  {
278  wxPoint pt( currentVertex.x, currentVertex.y );
279  wxString msg1 = zoneToTest->GetSelectMenuText();
280  wxString msg2 = zoneRef->GetSelectMenuText();
282  pt, msg1, pt, msg2, pt );
283  commit.Add( marker );
284  }
285 
286  nerrors++;
287  }
288  }
289 
290  // Iterate through all the segments of refSmoothedPoly
291  for( auto refIt = refSmoothedPoly.IterateSegmentsWithHoles(); refIt; refIt++ )
292  {
293  // Build ref segment
294  SEG refSegment = *refIt;
295 
296  // Iterate through all the segments in testSmoothedPoly
297  for( auto testIt = testSmoothedPoly.IterateSegmentsWithHoles(); testIt; testIt++ )
298  {
299  // Build test segment
300  SEG testSegment = *testIt;
301  wxPoint pt;
302 
303  int ax1, ay1, ax2, ay2;
304  ax1 = refSegment.A.x;
305  ay1 = refSegment.A.y;
306  ax2 = refSegment.B.x;
307  ay2 = refSegment.B.y;
308 
309  int bx1, by1, bx2, by2;
310  bx1 = testSegment.A.x;
311  by1 = testSegment.A.y;
312  bx2 = testSegment.B.x;
313  by2 = testSegment.B.y;
314 
315  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
316  0,
317  ax1, ay1, ax2, ay2,
318  0,
319  zone2zoneClearance,
320  &pt.x, &pt.y );
321 
322  if( d < zone2zoneClearance )
323  {
324  // COPPERAREA_COPPERAREA error : intersect or too close
325  if( aCreateMarkers )
326  {
327  wxString msg1 = zoneRef->GetSelectMenuText();
328  wxString msg2 = zoneToTest->GetSelectMenuText();
330  pt, msg1, pt, msg2, pt );
331  commit.Add( marker );
332  }
333 
334  nerrors++;
335  }
336  }
337  }
338  }
339  }
340 
341  if( aCreateMarkers )
342  commit.Push( wxEmptyString, false, false );
343 
344  return nerrors;
345 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
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
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly if it exists...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, bool aIgnoreHoles=false) const
Returns true if a given subpolygon contains the point aP.
#define COPPERAREA_INSIDE_COPPERAREA
copper area outlines intersect
Definition: drc.h:65
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)
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:780
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:602
#define COPPERAREA_CLOSE_TO_COPPERAREA
copper area outlines are too close
Definition: drc.h:66
ITERATOR IterateWithHoles(int aOutline)
Function IterateWithHoles.
Class SHAPE_POLY_SET.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
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:982
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
VECTOR2I A
Definition: seg.h:46
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:101
VECTOR2I B
Definition: seg.h:47
void DRC::updatePointers ( )
private

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

Definition at line 496 of file drc.cpp.

References PCB_BASE_FRAME::GetBoard(), 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 Drc(), ListUnconnectedPads(), RunTests(), and ShowDRCDialog().

497 {
498  // update my pointers, m_pcbEditorFrame is the only unchangeable one
500 
501  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
502  {
505 
507  }
508 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:211
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:753
void SetList(DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
BOARD * GetBoard() const
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc.h:210
DRCLISTBOX * m_ClearanceListBox
Class DRC_LIST_MARKERS is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD i...
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:209
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:213

Friends And Related Function Documentation

friend class DIALOG_DRC_CONTROL
friend

Definition at line 164 of file drc.h.

Referenced by ShowDRCDialog().

Member Data Documentation

bool DRC::m_abortDRC
private

Definition at line 183 of file drc.h.

Referenced by DRC().

bool DRC::m_doCreateRptFile
private

Definition at line 173 of file drc.h.

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

bool DRC::m_doFootprintOverlapping
private

Definition at line 174 of file drc.h.

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

bool DRC::m_doKeepoutTest
private

Definition at line 172 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doNoCourtyardDefined
private

Definition at line 175 of file drc.h.

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

bool DRC::m_doPad2PadTest
private

Definition at line 169 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doUnconnectedTest
private

Definition at line 170 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doZonesTest
private

Definition at line 171 of file drc.h.

Referenced by DRC().

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 211 of file drc.h.

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

bool DRC::m_drcInProgress
private

Definition at line 184 of file drc.h.

Referenced by DRC().

wxPoint DRC::m_padToTestPos
private

Definition at line 190 of file drc.h.

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

PCB_EDIT_FRAME* DRC::m_pcbEditorFrame
private

The pcb frame editor which owns the board.

Definition at line 209 of file drc.h.

Referenced by addMarkerToPcb(), doTrackDrc(), DRC(), Drc(), RunTests(), ShowDRCDialog(), TestZoneToZoneOutline(), and updatePointers().

bool DRC::m_refillZones
private

Definition at line 176 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_reportAllTrackErrors
private

Definition at line 177 of file drc.h.

Referenced by doTrackDrc(), and DRC().

wxString DRC::m_rptFilename
private

Definition at line 179 of file drc.h.

Referenced by DestroyDRCDialog(), and ShowDRCDialog().

double DRC::m_segmAngle
private

Definition at line 198 of file drc.h.

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

wxPoint DRC::m_segmEnd
private

Definition at line 191 of file drc.h.

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

int DRC::m_segmLength
private

Definition at line 199 of file drc.h.

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

DRC_LIST DRC::m_unconnected
private

list of unconnected pads, as DRC_ITEMs

Definition at line 213 of file drc.h.

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

int DRC::m_xcliphi
private

Definition at line 206 of file drc.h.

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

int DRC::m_xcliplo
private

Definition at line 204 of file drc.h.

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

int DRC::m_ycliphi
private

Definition at line 207 of file drc.h.

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

int DRC::m_ycliplo
private

Definition at line 205 of file drc.h.

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


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