KiCad PCB EDA Suite
DRC Class Reference

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

#include <drc.h>

Public Member Functions

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

Private Member Functions

void updatePointers ()
 Update needed pointers from the one pointer which is known not to change. More...
 
MARKER_PCBfillMarker (TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
 Function fillMarker Optionally 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 (BOARD_ITEM *aItem, const wxPoint &aPos, int aErrorCode, MARKER_PCB *fillMe)
 Function fillMarker Optionally creates a marker and fills it in with information, but does not add it to the BOARD. More...
 
MARKER_PCBfillMarker (const wxPoint &aPos, BOARD_ITEM *aItem, BOARD_ITEM *bItem, int aErrorCode, MARKER_PCB *fillMe)
 Function fillMarker Optionally creates a marker and fills it in with information, but does 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 testDrilledHoles ()
 
void testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testTexts ()
 
void testDisabledLayers ()
 

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

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

Static Private Member Functions

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

Private Attributes

bool m_doPad2PadTest
 
bool m_doUnconnectedTest
 
bool m_doZonesTest
 
bool m_doKeepoutTest
 
bool m_doCreateRptFile
 
bool m_refillZones
 
bool m_reportAllTrackErrors
 
wxString m_rptFilename
 
MARKER_PCBm_currentMarker
 
bool m_drcInLegacyRoutingMode
 in legacy canvas, when creating a track, the drc test must only display the error message, and do not create a DRC marker. More...
 
wxPoint m_padToTestPos
 
wxPoint m_segmEnd
 
double m_segmAngle
 
int m_segmLength
 
int m_xcliplo
 
int m_ycliplo
 
int m_xcliphi
 
int m_ycliphi
 
PCB_EDIT_FRAMEm_pcbEditorFrame
 The pcb frame editor which owns the board. More...
 
BOARDm_pcb
 
DIALOG_DRC_CONTROLm_drcDialog
 
EDA_UNITS_T m_units
 
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 164 of file drc.h.

Constructor & Destructor Documentation

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 129 of file drc.cpp.

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

130 {
131  m_pcbEditorFrame = aPcbWindow;
132  m_pcb = aPcbWindow->GetBoard();
133  m_drcDialog = NULL;
134  m_units = aPcbWindow->GetUserUnits();
135 
136  // establish initial values for everything:
137  m_drcInLegacyRoutingMode = false;
138  m_doPad2PadTest = true; // enable pad to pad clearance tests
139  m_doUnconnectedTest = true; // enable unconnected tests
140  m_doZonesTest = true; // enable zone to items clearance tests
141  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
142  m_refillZones = false; // Only fill zones if requested by user.
143  m_reportAllTrackErrors = false;
144  m_doCreateRptFile = false;
145 
146  // m_rptFilename set to empty by its constructor
147 
148  m_currentMarker = NULL;
149 
150  m_segmAngle = 0;
151  m_segmLength = 0;
152 
153  m_xcliplo = 0;
154  m_ycliplo = 0;
155  m_xcliphi = 0;
156  m_ycliphi = 0;
157 }
bool m_refillZones
Definition: drc.h:176
bool m_doCreateRptFile
Definition: drc.h:175
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:216
int m_ycliplo
Definition: drc.h:210
int m_ycliphi
Definition: drc.h:212
int m_segmLength
Definition: drc.h:204
BOARD * GetBoard() const
BOARD * m_pcb
Definition: drc.h:215
bool m_doKeepoutTest
Definition: drc.h:174
bool m_doZonesTest
Definition: drc.h:173
EDA_UNITS_T GetUserUnits() const override
Function GetUserUnits returns the user units currently in use.
Definition: draw_frame.h:268
EDA_UNITS_T m_units
Definition: drc.h:217
bool m_reportAllTrackErrors
Definition: drc.h:177
int m_xcliphi
Definition: drc.h:211
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
bool m_doPad2PadTest
Definition: drc.h:171
MARKER_PCB * m_currentMarker
Definition: drc.h:181
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:189
int m_xcliplo
Definition: drc.h:209
bool m_doUnconnectedTest
Definition: drc.h:172
double m_segmAngle
Definition: drc.h:203
DRC::~DRC ( )

Definition at line 160 of file drc.cpp.

References i, and m_unconnected.

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

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_currentMarker, m_drcInLegacyRoutingMode, m_pcbEditorFrame, BOARD_COMMIT::Push(), and EDA_DRAW_FRAME::SetMsgPanel().

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

99 {
100  // In legacy routing mode, do not add markers to the board.
101  // only shows the drc error message
103  {
104  m_pcbEditorFrame->SetMsgPanel( aMarker );
105  delete aMarker;
106  m_currentMarker = nullptr;
107  }
108  else
109  {
110  BOARD_COMMIT commit( m_pcbEditorFrame );
111  commit.Add( aMarker );
112  commit.Push( wxEmptyString, false, false );
113  }
114 }
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:854
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
MARKER_PCB * m_currentMarker
Definition: drc.h:181
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:189
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 784 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().

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

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

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

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

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1316 {
1317  if( abs( aCentre.y ) >= aRadius ) // trivial case
1318  return true;
1319 
1320  // Here, distance between aCentre and X axis is < aRadius
1321  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1322  {
1323  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1324  return false; // aCentre is between the starting point and the ending point of the segm
1325 
1326  if( aCentre.x > aLength ) // aCentre is after the ending point
1327  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1328 
1329  if( EuclideanNorm( aCentre ) < aRadius )
1330  // distance between aCentre and the starting point or the ending point is < aRadius
1331  return false;
1332  }
1333 
1334  return true;
1335 }
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 117 of file drc.cpp.

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

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

118 {
119  if( m_drcDialog )
120  {
122 
123  m_drcDialog->Destroy();
124  m_drcDialog = NULL;
125  }
126 }
bool m_doCreateRptFile
Definition: drc.h:175
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:216
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:213
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 684 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 DrcOnCreatingZone().

685 {
686  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
687  return true;
688  // Get polygon, contour and vertex index.
690 
691  // If the vertex does not exist, there is no conflict
692  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
693  return true;
694 
695  // Retrieve the selected contour
696  SHAPE_LINE_CHAIN contour;
697  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
698 
699  // Retrieve the segment that starts at aCornerIndex-th corner.
700  SEG selectedSegment = contour.Segment( index.m_vertex );
701 
702  VECTOR2I start = selectedSegment.A;
703  VECTOR2I end = selectedSegment.B;
704 
705  // iterate through all areas
706  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
707  {
708  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
709  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
710  aArea->GetZoneClearance() );
711 
712  // test for same layer
713  if( area_to_test->GetLayer() != aArea->GetLayer() )
714  continue;
715 
716  // Test for same net
717  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
718  continue;
719 
720  // test for same priority
721  if( area_to_test->GetPriority() != aArea->GetPriority() )
722  continue;
723 
724  // test for same type
725  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
726  continue;
727 
728  // For keepout, there is no clearance, so use a minimal value for it
729  // use 1, not 0 as value to avoid some issues in tests
730  if( area_to_test->GetIsKeepout() )
731  zone_clearance = 1;
732 
733  // test for ending line inside area_to_test
734  if( area_to_test->Outline()->Contains( end ) )
735  {
736  // COPPERAREA_COPPERAREA error: corner inside copper area
737  m_currentMarker = fillMarker( aArea, static_cast<wxPoint>( end ),
739  m_currentMarker );
740  return false;
741  }
742 
743  // now test spacing between areas
744  int ax1 = start.x;
745  int ay1 = start.y;
746  int ax2 = end.x;
747  int ay2 = end.y;
748 
749  // Iterate through all edges in the polygon.
751  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
752  {
753  SEG segment = *iterator;
754 
755  int bx1 = segment.A.x;
756  int by1 = segment.A.y;
757  int bx2 = segment.B.x;
758  int by2 = segment.B.y;
759 
760  int x, y; // variables containing the intersecting point coordinates
761  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
762  0,
763  ax1, ay1, ax2, ay2,
764  0,
765  zone_clearance,
766  &x, &y );
767 
768  if( d < zone_clearance )
769  {
770  // COPPERAREA_COPPERAREA error : edge intersect or too close
771  m_currentMarker = fillMarker( aArea, wxPoint( x, y ),
773  m_currentMarker );
774  return false;
775  }
776 
777  }
778  }
779 
780  return true;
781 }
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)
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:215
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:1017
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:988
#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
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
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 1316 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(), BOARD::GetDesignSettings(), m_currentMarker, BOARD::m_Modules, m_pcb, BOARD_DESIGN_SETTINGS::m_ProhibitOverlappingCourtyards, BOARD_DESIGN_SETTINGS::m_RequireCourtyards, 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().

1317 {
1318  // Detects missing (or malformed) footprint courtyard,
1319  // and for footprint with courtyard, courtyards overlap.
1320  wxString msg;
1321  bool success = true;
1322 
1323  // Update courtyard polygons, and test for missing courtyard definition:
1324  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1325  {
1326  bool is_ok = footprint->BuildPolyCourtyard();
1327 
1329  {
1330  m_currentMarker = fillMarker( footprint, footprint->GetPosition(),
1332  m_currentMarker );
1334  m_currentMarker = nullptr;
1335  success = false;
1336  }
1337 
1339  continue;
1340 
1341  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 &&
1342  footprint->GetPolyCourtyardBack().OutlineCount() == 0 &&
1343  is_ok )
1344  {
1345  m_currentMarker = fillMarker( footprint, footprint->GetPosition(),
1347  m_currentMarker );
1349  m_currentMarker = nullptr;
1350  success = false;
1351  }
1352  }
1353 
1355  return success;
1356 
1357  // Now test for overlapping on top layer:
1358  SHAPE_POLY_SET courtyard; // temporary storage of the courtyard of current footprint
1359 
1360  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1361  {
1362  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 )
1363  continue; // No courtyard defined
1364 
1365  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1366  {
1367  if( candidate->GetPolyCourtyardFront().OutlineCount() == 0 )
1368  continue; // No courtyard defined
1369 
1370  courtyard.RemoveAllContours();
1371  courtyard.Append( footprint->GetPolyCourtyardFront() );
1372 
1373  // Build the common area between footprint and the candidate:
1374  courtyard.BooleanIntersection( candidate->GetPolyCourtyardFront(),
1376 
1377  // If no overlap, courtyard is empty (no common area).
1378  // Therefore if a common polygon exists, this is a DRC error
1379  if( courtyard.OutlineCount() )
1380  {
1381  //Overlap between footprint and candidate
1382  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1383  m_currentMarker = fillMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
1386  m_currentMarker = nullptr;
1387  success = false;
1388  }
1389  }
1390  }
1391 
1392  // Test for overlapping on bottom layer:
1393  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1394  {
1395  if( footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
1396  continue; // No courtyard defined
1397 
1398  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1399  {
1400  if( candidate->GetPolyCourtyardBack().OutlineCount() == 0 )
1401  continue; // No courtyard defined
1402 
1403  courtyard.RemoveAllContours();
1404  courtyard.Append( footprint->GetPolyCourtyardBack() );
1405 
1406  // Build the common area between footprint and the candidate:
1407  courtyard.BooleanIntersection( candidate->GetPolyCourtyardBack(),
1409 
1410  // If no overlap, courtyard is empty (no common area).
1411  // Therefore if a common polygon exists, this is a DRC error
1412  if( courtyard.OutlineCount() )
1413  {
1414  //Overlap between footprint and candidate
1415  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1416  m_currentMarker = fillMarker( wxPoint( pos.x, pos.y ), footprint, candidate,
1419  m_currentMarker = nullptr;
1420  success = false;
1421  }
1422  }
1423  }
1424 
1425  return success;
1426 }
bool m_ProhibitOverlappingCourtyards
check for overlapping courtyards in DRC
MODULE * Next() const
Definition: class_module.h:123
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:215
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.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:537
#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
bool m_RequireCourtyards
require courtyard definitions in footprints
DLIST< MODULE > m_Modules
Definition: class_board.h:247
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
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 562 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().

563 {
564  bool ret = true;
565 
567 
568 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
569 
570 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
571  if( nc->GetClearance() < g.m_MinClearance )
572  {
573  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
574  GetChars( nc->GetName() ),
575  FmtVal( nc->GetClearance() ),
576  FmtVal( g.m_TrackClearance )
577  );
578 
580  m_currentMarker = nullptr;
581  ret = false;
582  }
583 #endif
584 
585  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
586  {
587  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
588  GetChars( nc->GetName() ),
589  FmtVal( nc->GetTrackWidth() ),
591  );
592 
594  m_currentMarker = nullptr;
595  ret = false;
596  }
597 
598  if( nc->GetViaDiameter() < g.m_ViasMinSize )
599  {
600  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
601  GetChars( nc->GetName() ),
602  FmtVal( nc->GetViaDiameter() ),
603  FmtVal( g.m_ViasMinSize )
604  );
605 
607  m_currentMarker = nullptr;
608  ret = false;
609  }
610 
611  if( nc->GetViaDrill() < g.m_ViasMinDrill )
612  {
613  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
614  GetChars( nc->GetName() ),
615  FmtVal( nc->GetViaDrill() ),
617  );
618 
620  m_currentMarker = nullptr;
621  ret = false;
622  }
623 
624  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
625  {
626  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
627  GetChars( nc->GetName() ),
628  FmtVal( nc->GetuViaDiameter() ),
630  );
631 
633  m_currentMarker = nullptr;
634  ret = false;
635  }
636 
637  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
638  {
639  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
640  GetChars( nc->GetName() ),
641  FmtVal( nc->GetuViaDrill() ),
643  );
644 
646  m_currentMarker = nullptr;
647  ret = false;
648  }
649 
650  return ret;
651 }
#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:215
#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:537
#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
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
#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
aRefPadis the pad to test
aStartis the first pad of the list to test against aRefPad
aEndis the end of the list and is not included
x_limitis used to stop the test (i.e. when the current pad pos X in list exceeds this limit, because the list is sorted by X coordinate)

Definition at line 1182 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().

1183 {
1184  const static LSET all_cu = LSET::AllCuMask();
1185 
1186  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1187 
1188  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1189  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1190  * Therefore, this dummy pad is a circle or an oval.
1191  * A pad must have a parent because some functions expect a non null parent
1192  * to find the parent board, and some other data
1193  */
1194  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1195  D_PAD dummypad( &dummymodule );
1196 
1197  // Ensure the hole is on all copper layers
1198  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1199 
1200  // Use the minimal local clearance value for the dummy pad.
1201  // The clearance of the active pad will be used as minimum distance to a hole
1202  // (a value = 0 means use netclass value)
1203  dummypad.SetLocalClearance( 1 );
1204 
1205  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1206  {
1207  D_PAD* pad = *pad_list;
1208 
1209  if( pad == aRefPad )
1210  continue;
1211 
1212  // We can stop the test when pad->GetPosition().x > x_limit
1213  // because the list is sorted by X values
1214  if( pad->GetPosition().x > x_limit )
1215  break;
1216 
1217  // No problem if pads which are on copper layers are on different copper layers,
1218  // (pads can be only on a technical layer, to build complex pads)
1219  // but their hole (if any ) can create DRC error because they are on all
1220  // copper layers, so we test them
1221  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1222  ( pad->GetLayerSet() & all_cu ) != 0 &&
1223  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1224  {
1225  // if holes are in the same location and have the same size and shape,
1226  // this can be accepted
1227  if( pad->GetPosition() == aRefPad->GetPosition()
1228  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1229  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1230  {
1231  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1232  continue;
1233 
1234  // for oval holes: must also have the same orientation
1235  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1236  continue;
1237  }
1238 
1239  /* Here, we must test clearance between holes and pads
1240  * dummy pad size and shape is adjusted to pad drill size and shape
1241  */
1242  if( pad->GetDrillSize().x )
1243  {
1244  // pad under testing has a hole, test this hole against pad reference
1245  dummypad.SetPosition( pad->GetPosition() );
1246  dummypad.SetSize( pad->GetDrillSize() );
1247  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1249  dummypad.SetOrientation( pad->GetOrientation() );
1250 
1251  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1252  {
1253  // here we have a drc error on pad!
1254  m_currentMarker = fillMarker( pad, aRefPad,
1256  return false;
1257  }
1258  }
1259 
1260  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1261  {
1262  dummypad.SetPosition( aRefPad->GetPosition() );
1263  dummypad.SetSize( aRefPad->GetDrillSize() );
1264  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1266  dummypad.SetOrientation( aRefPad->GetOrientation() );
1267 
1268  if( !checkClearancePadToPad( pad, &dummypad ) )
1269  {
1270  // here we have a drc error on aRefPad!
1271  m_currentMarker = fillMarker( aRefPad, pad,
1273  return false;
1274  }
1275  }
1276 
1277  continue;
1278  }
1279 
1280  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1281  // But no problem if pads have the same netcode (same net)
1282  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1283  continue;
1284 
1285  // if pads are from the same footprint
1286  if( pad->GetParent() == aRefPad->GetParent() )
1287  {
1288  // and have the same pad number ( equivalent pads )
1289 
1290  // one can argue that this 2nd test is not necessary, that any
1291  // two pads from a single module are acceptable. This 2nd test
1292  // should eventually be a configuration option.
1293  if( pad->PadNameEqual( aRefPad ) )
1294  continue;
1295  }
1296 
1297  // if either pad has no drill and is only on technical layers, not a clearance violation
1298  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1299  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1300  {
1301  continue;
1302  }
1303 
1304  if( !checkClearancePadToPad( aRefPad, pad ) )
1305  {
1306  // here we have a drc error!
1308  return false;
1309  }
1310  }
1311 
1312  return true;
1313 }
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
#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:215
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
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
bool DRC::doTrackDrc ( TRACK aRefSeg,
TRACK aStart,
bool  doPads = true 
)
private

Test the current segment.

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

Definition at line 138 of file drc_clearance_test_functions.cpp.

References abs, COMMIT::Add(), 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, m_drcInLegacyRoutingMode, BOARD_DESIGN_SETTINGS::m_MicroViasAllowed, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, m_padToTestPos, m_pcb, m_pcbEditorFrame, m_reportAllTrackErrors, m_segmAngle, m_segmEnd, m_segmLength, BOARD_DESIGN_SETTINGS::m_TrackMinWidth, BOARD_DESIGN_SETTINGS::m_ViasMinDrill, BOARD_DESIGN_SETTINGS::m_ViasMinSize, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, TRACK::Next(), PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PCB_VIA_T, BOARD_COMMIT::Push(), RotatePoint(), D_PAD::SetLayerSet(), EDA_DRAW_FRAME::SetMsgPanel(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), D_PAD::SetSize(), D_PAD::ShapePos(), EDA_ITEM::Type(), VIA_BLIND_BURIED, VIA_MICROVIA, wxPoint::x, and wxPoint::y.

Referenced by DrcOnCreatingTrack(), and testTracks().

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

1134 {
1135  // Test keepout areas for vias, tracks and pads inside keepout areas
1136  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
1137  {
1138  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
1139 
1140  if( !area->GetIsKeepout() )
1141  continue;
1142 
1143  if( aRefSeg->Type() == PCB_TRACE_T )
1144  {
1145  if( !area->GetDoNotAllowTracks() )
1146  continue;
1147 
1148  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
1149  continue;
1150 
1151  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
1152  aRefSeg->GetWidth() ) == 0 )
1153  {
1154  m_currentMarker = fillMarker( aRefSeg, NULL,
1156  return false;
1157  }
1158  }
1159  else if( aRefSeg->Type() == PCB_VIA_T )
1160  {
1161  if( !area->GetDoNotAllowVias() )
1162  continue;
1163 
1164  auto viaLayers = aRefSeg->GetLayerSet();
1165 
1166  if( !area->CommonLayerExists( viaLayers ) )
1167  continue;
1168 
1169  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
1170  {
1171  m_currentMarker = fillMarker( aRefSeg, NULL,
1173  return false;
1174  }
1175  }
1176  }
1177 
1178  return true;
1179 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
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
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:215
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:1017
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:988
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
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
int DRC::DrcOnCreatingTrack ( TRACK aRefSeg,
TRACK aList 
)

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

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

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

Definition at line 168 of file drc.cpp.

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

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

169 {
170  updatePointers();
171 
172  // Set right options for this on line drc
173  int drc_state = m_drcInLegacyRoutingMode;
175  int rpt_state = m_reportAllTrackErrors;
176  m_reportAllTrackErrors = false;
177 
178  if( !doTrackDrc( aRefSegm, aList, true ) )
179  {
180  if( m_currentMarker )
182 
183  m_drcInLegacyRoutingMode = drc_state;
184  m_reportAllTrackErrors = rpt_state;
185  return BAD_DRC;
186  }
187 
188  if( !doTrackKeepoutDrc( aRefSegm ) )
189  {
190  wxASSERT( m_currentMarker );
191 
193  delete m_currentMarker;
194  m_currentMarker = nullptr;
195  m_drcInLegacyRoutingMode = drc_state;
196  m_reportAllTrackErrors = rpt_state;
197  return BAD_DRC;
198  }
199 
200  m_drcInLegacyRoutingMode = drc_state;
201  m_reportAllTrackErrors = rpt_state;
202  return OK_DRC;
203 }
#define OK_DRC
Definition: drc.h:35
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Test the current segment or via.
Definition: drc.cpp:1133
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:854
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:545
bool m_reportAllTrackErrors
Definition: drc.h:177
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
#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.
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:189
int DRC::DrcOnCreatingZone ( ZONE_CONTAINER aArea,
int  aCornerIndex 
)

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

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

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

Definition at line 362 of file drc.cpp.

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

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

363 {
364  updatePointers();
365 
366  // Set right options for this on line drc
367  int drc_state = m_drcInLegacyRoutingMode;
369  int rpt_state = m_reportAllTrackErrors;
370  m_reportAllTrackErrors = false;
371 
372  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
373  {
374  wxASSERT( m_currentMarker );
376  delete m_currentMarker;
377  m_currentMarker = nullptr;
378  m_drcInLegacyRoutingMode = drc_state;
379  m_reportAllTrackErrors = rpt_state;
380  return BAD_DRC;
381  }
382 
383  m_drcInLegacyRoutingMode = drc_state;
384  m_reportAllTrackErrors = rpt_state;
385  return OK_DRC;
386 }
#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:854
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:545
bool m_reportAllTrackErrors
Definition: drc.h:177
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
#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
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:189
MARKER_PCB * DRC::fillMarker ( TRACK aTrack,
BOARD_ITEM aItem,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Function fillMarker Optionally 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
aTrack/aPadThe reference item.
aItemAnother item on the BOARD, such as a VIA, SEGZONE, or TRACK, which is in conflict with the reference item.
aErrorCodeAn ID 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 be created.

Definition at line 49 of file drc_marker_functions.cpp.

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

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

50 {
51  wxPoint posA;
52  wxPoint posB = wxPoint();
53 
54  if( bItem ) // aItem might be NULL
55  {
56  if( bItem->Type() == PCB_PAD_T )
57  {
58  posB = posA = ((D_PAD*)bItem)->GetPosition();
59  }
60  else if( bItem->Type() == PCB_VIA_T )
61  {
62  posB = posA = ((VIA*)bItem)->GetPosition();
63  }
64  else if( bItem->Type() == PCB_TRACE_T )
65  {
66  TRACK* track = (TRACK*) bItem;
67 
68  posB = track->GetPosition();
69 
70  wxPoint endPos = track->GetEnd();
71 
72  // either of aItem's start or end will be used for the marker position
73  // first assume start, then switch at end if needed. decision made on
74  // distance from end of aTrack.
75  posA = track->GetStart();
76 
77  double dToEnd = GetLineLength( endPos, aTrack->GetEnd() );
78  double dToStart = GetLineLength( posA, aTrack->GetEnd() );
79 
80  if( dToEnd < dToStart )
81  posA = endPos;
82  }
83  else if( bItem->Type() == PCB_TEXT_T )
84  {
85  posA = aTrack->GetPosition();
86  posB = ((TEXTE_PCB*) bItem)->GetPosition();
87  }
88  }
89  else
90  posA = aTrack->GetPosition();
91 
92  if( fillMe )
93  fillMe->SetData( m_units, aErrorCode, posA, aTrack, aTrack->GetPosition(), bItem, posB );
94  else
95  fillMe = new MARKER_PCB( m_units, aErrorCode, posA, aTrack, aTrack->GetPosition(), bItem, posB );
96 
97  return fillMe;
98 }
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
void SetData(EDA_UNITS_T aUnits, int aErrorCode, const wxPoint &aMarkerPos, EDA_ITEM *aItem, const wxPoint &aPos, EDA_ITEM *bItem=nullptr, const wxPoint &bPos=wxPoint())
Function SetData fills in all the reportable data associated with a MARKER.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
const wxPoint & GetEnd() const
Definition: class_track.h:119
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
const wxPoint GetPosition() const override
Definition: class_track.h:113
const wxPoint & GetStart() const
Definition: class_track.h:122
EDA_UNITS_T m_units
Definition: drc.h:217
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 101 of file drc_marker_functions.cpp.

References D_PAD::GetPosition(), m_units, PCB_PAD_T, PCB_TEXT_T, MARKER_BASE::SetData(), and EDA_ITEM::Type().

102 {
103  wxPoint posA = aPad->GetPosition();
104  wxPoint posB;
105 
106  if( aItem )
107  {
108  switch( aItem->Type() )
109  {
110  case PCB_PAD_T:
111  posB = ((D_PAD*)aItem)->GetPosition();
112  break;
113 
114  case PCB_TEXT_T:
115  posB = ((TEXTE_PCB*)aItem)->GetPosition();
116  break;
117 
118  default:
119  wxLogDebug( wxT("fillMarker: unsupported item") );
120  break;
121  }
122  }
123 
124  if( fillMe )
125  fillMe->SetData( m_units, aErrorCode, posA, aPad, posA, aItem, posB );
126  else
127  fillMe = new MARKER_PCB( m_units, aErrorCode, posA, aPad, posA, aItem, posB );
128 
129  return fillMe;
130 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
void SetData(EDA_UNITS_T aUnits, int aErrorCode, const wxPoint &aMarkerPos, EDA_ITEM *aItem, const wxPoint &aPos, EDA_ITEM *bItem=nullptr, const wxPoint &bPos=wxPoint())
Function SetData fills in all the reportable data associated with a MARKER.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
EDA_UNITS_T m_units
Definition: drc.h:217
const wxPoint GetPosition() const override
Definition: class_pad.h:220
MARKER_PCB * DRC::fillMarker ( BOARD_ITEM aItem,
const wxPoint aPos,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Function fillMarker Optionally 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
aItemThe reference item.
aPosUsually the position of the item, but could be more specific for a zone.
aErrorCodeAn ID for the particular type of error that is being reported.
fillMeA MARKER_PCB* which is to be filled in, or NULL if one is to be created.

Definition at line 133 of file drc_marker_functions.cpp.

References fillMarker().

135 {
136  return fillMarker(aPos, aItem, nullptr, aErrorCode, fillMe );
137 }
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
MARKER_PCB * DRC::fillMarker ( const wxPoint aPos,
BOARD_ITEM aItem,
BOARD_ITEM bItem,
int  aErrorCode,
MARKER_PCB fillMe 
)
private

Function fillMarker Optionally 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
aPosThe reference location.
aErrorCodeAn ID for the particular type of error that is being reported.
aItemThe first item in conflict.
bItem(Optional) The second item in conflict or NULL.
aErrorCodeAn ID 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 be created.

Definition at line 140 of file drc_marker_functions.cpp.

References m_units, and MARKER_BASE::SetData().

142 {
143  if( fillMe )
144  fillMe->SetData( m_units, aErrorCode, aPos, aItem, aPos, bItem, aPos );
145  else
146  fillMe = new MARKER_PCB( m_units, aErrorCode, aPos, aItem, aPos, bItem, aPos );
147 
148  return fillMe;
149 }
void SetData(EDA_UNITS_T aUnits, int aErrorCode, const wxPoint &aMarkerPos, EDA_ITEM *aItem, const wxPoint &aPos, EDA_ITEM *bItem=nullptr, const wxPoint &bPos=wxPoint())
Function SetData fills in all the reportable data associated with a MARKER.
EDA_UNITS_T m_units
Definition: drc.h:217
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 152 of file drc_marker_functions.cpp.

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

153 {
154  wxPoint posA; // not displayed
155 
156  if( fillMe )
157  fillMe->SetData( aErrorCode, posA, aMessage, posA );
158  else
159  fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
160 
161  fillMe->SetShowNoCoordinate();
162 
163  return fillMe;
164 }
void SetShowNoCoordinate()
Definition: marker_base.h:208
void SetData(EDA_UNITS_T aUnits, int aErrorCode, const wxPoint &aMarkerPos, EDA_ITEM *aItem, const wxPoint &aPos, EDA_ITEM *bItem=nullptr, const wxPoint &bPos=wxPoint())
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 536 of file drc.cpp.

References testUnconnected(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick().

537 {
538  testUnconnected();
539 
540  // update the m_drcDialog listboxes
541  updatePointers();
542 }
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
Definition: drc.cpp:545
void testUnconnected()
Definition: drc.cpp:853
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 389 of file drc.cpp.

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

Referenced by DIALOG_DRC_CONTROL::OnStartdrcClick().

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

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

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

Definition at line 511 of file drc.h.

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

515  {
516  m_doPad2PadTest = aPad2PadTest;
517  m_doUnconnectedTest = aUnconnectedTest;
518  m_doZonesTest = aZonesTest;
519  m_doKeepoutTest = aKeepoutTest;
520  m_rptFilename = aReportName;
521  m_doCreateRptFile = aSaveReport;
522  m_refillZones = aRefillZones;
523  m_drcInLegacyRoutingMode = false;
524  m_reportAllTrackErrors = aReportAllTrackErrors;
525  }
bool m_refillZones
Definition: drc.h:176
bool m_doCreateRptFile
Definition: drc.h:175
bool m_doKeepoutTest
Definition: drc.h:174
bool m_doZonesTest
Definition: drc.h:173
bool m_reportAllTrackErrors
Definition: drc.h:177
bool m_doPad2PadTest
Definition: drc.h:171
wxString m_rptFilename
Definition: drc.h:179
bool m_drcInLegacyRoutingMode
in legacy canvas, when creating a track, the drc test must only display the error message...
Definition: drc.h:189
bool m_doUnconnectedTest
Definition: drc.h:172
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:175
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:216
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:545
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
bool Show(bool show) override
friend class DIALOG_DRC_CONTROL
Definition: drc.h:166
TOOL_MANAGER * GetToolManager() const
Function GetToolManager returns the tool manager instance, if any.
Definition: draw_frame.h:911
wxString m_rptFilename
Definition: drc.h:179
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:206
void DRC::testDisabledLayers ( )
private

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

Definition at line 1096 of file drc.cpp.

References addMarkerToPcb(), DRCE_DISABLED_LAYER_ITEM, fillMarker(), PCB_BASE_FRAME::GetBoard(), BOARD::GetEnabledLayers(), BOARD_ITEM::GetLayer(), m_currentMarker, m_pcbEditorFrame, BOARD::Modules(), BOARD::Tracks(), and BOARD::Zones().

Referenced by RunTests().

1097 {
1098  BOARD* board = m_pcbEditorFrame->GetBoard();
1099  wxCHECK( board, /*void*/ );
1100  LSET disabledLayers = board->GetEnabledLayers().flip();
1101 
1102  auto createMarker = [&]( BOARD_ITEM* aItem )
1103  {
1104  m_currentMarker = fillMarker( aItem, aItem->GetPosition(), DRCE_DISABLED_LAYER_ITEM,
1105  m_currentMarker );
1107  m_currentMarker = nullptr;
1108  };
1109 
1110  for( auto track : board->Tracks() )
1111  {
1112  if( disabledLayers.test( track->GetLayer() ) )
1113  createMarker( track );
1114  }
1115 
1116  for( auto module : board->Modules() )
1117  {
1118  module->RunOnChildren( [&]( BOARD_ITEM* aItem )
1119  {
1120  if( disabledLayers.test( aItem->GetLayer() ) )
1121  createMarker( aItem );
1122  } );
1123  }
1124 
1125  for( auto zone : board->Zones() )
1126  {
1127  if( disabledLayers.test( zone->GetLayer() ) )
1128  createMarker( zone );
1129  }
1130 }
#define DRCE_DISABLED_LAYER_ITEM
item on a disabled layer
Definition: drc.h:93
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
BOARD * GetBoard() const
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: drc.cpp:98
Class LSET is a set of PCB_LAYER_IDs.
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:253
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
MARKER_PCB * m_currentMarker
Definition: drc.h:181
ZONE_CONTAINERS & Zones()
Definition: class_board.h:255
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:252
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
void DRC::testDrilledHoles ( )
private

Definition at line 721 of file drc.cpp.

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

Referenced by RunTests().

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

Definition at line 919 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().

920 {
921  // Test keepout areas for vias, tracks and pads inside keepout areas
922  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
923  {
924  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
925 
926  if( !area->GetIsKeepout() )
927  {
928  continue;
929  }
930 
931  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
932  {
933  if( segm->Type() == PCB_TRACE_T )
934  {
935  if( !area->GetDoNotAllowTracks() )
936  continue;
937 
938  // Ignore if the keepout zone is not on the same layer
939  if( !area->IsOnLayer( segm->GetLayer() ) )
940  continue;
941 
942  if( area->Outline()->Distance( SEG( segm->GetStart(), segm->GetEnd() ),
943  segm->GetWidth() ) == 0 )
944  {
945  addMarkerToPcb( fillMarker( segm, NULL,
947  m_currentMarker = nullptr;
948  }
949  }
950  else if( segm->Type() == PCB_VIA_T )
951  {
952  if( ! area->GetDoNotAllowVias() )
953  continue;
954 
955  auto viaLayers = segm->GetLayerSet();
956 
957  if( !area->CommonLayerExists( viaLayers ) )
958  continue;
959 
960  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
961  {
962  addMarkerToPcb( fillMarker( segm, NULL,
964  m_currentMarker = nullptr;
965  }
966  }
967  }
968  // Test pads: TODO
969  }
970 }
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
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:215
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:1017
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:988
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:248
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
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 654 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().

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

Definition at line 677 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().

678 {
679  std::vector<D_PAD*> sortedPads;
680 
681  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
682 
683  if( sortedPads.size() == 0 )
684  return;
685 
686  // find the max size of the pads (used to stop the test)
687  int max_size = 0;
688 
689  for( unsigned i = 0; i < sortedPads.size(); ++i )
690  {
691  D_PAD* pad = sortedPads[i];
692 
693  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
694  int radius = pad->GetBoundingRadius();
695 
696  if( radius > max_size )
697  max_size = radius;
698  }
699 
700  // Upper limit of pad list (limit not included)
701  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
702 
703  // Test the pads
704  for( unsigned i = 0; i< sortedPads.size(); ++i )
705  {
706  D_PAD* pad = sortedPads[i];
707 
708  int x_limit = max_size + pad->GetClearance() +
709  pad->GetBoundingRadius() + pad->GetPosition().x;
710 
711  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
712  {
713  wxASSERT( m_currentMarker );
715  m_currentMarker = nullptr;
716  }
717  }
718 }
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:215
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:603
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:1182
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:554
const wxPoint GetPosition() const override
Definition: class_pad.h:220
void DRC::testTexts ( )
private

Definition at line 973 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().

974 {
975  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
976  std::vector<D_PAD*> padList = m_pcb->GetPads();
977 
978  // Test text areas for vias, tracks and pads inside text areas
979  for( auto item : m_pcb->Drawings() )
980  {
981  // Drc test only items on copper layers
982  if( !IsCopperLayer( item->GetLayer() ) )
983  continue;
984 
985  // only texts on copper layers are tested
986  if( item->Type() != PCB_TEXT_T )
987  continue;
988 
989  textShape.clear();
990 
991  // So far the bounding box makes up the text-area
992  TEXTE_PCB* text = (TEXTE_PCB*) item;
993  text->TransformTextShapeToSegmentList( textShape );
994 
995  if( textShape.size() == 0 ) // Should not happen (empty text?)
996  continue;
997 
998  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
999  {
1000  if( !track->IsOnLayer( item->GetLayer() ) )
1001  continue;
1002 
1003  // Test the distance between each segment and the current track/via
1004  int min_dist = ( track->GetWidth() + text->GetThickness() ) /2 +
1005  track->GetClearance(NULL);
1006 
1007  if( track->Type() == PCB_TRACE_T )
1008  {
1009  SEG segref( track->GetStart(), track->GetEnd() );
1010 
1011  // Error condition: Distance between text segment and track segment is
1012  // smaller than the clearance of the segment
1013  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1014  {
1015  SEG segtest( textShape[jj], textShape[jj+1] );
1016  int dist = segref.Distance( segtest );
1017 
1018  if( dist < min_dist )
1019  {
1020  addMarkerToPcb( fillMarker( track, text,
1022  m_currentMarker = nullptr;
1023  break;
1024  }
1025  }
1026  }
1027  else if( track->Type() == PCB_VIA_T )
1028  {
1029  // Error condition: Distance between text segment and via is
1030  // smaller than the clearance of the via
1031  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1032  {
1033  SEG segtest( textShape[jj], textShape[jj+1] );
1034 
1035  if( segtest.PointCloserThan( track->GetPosition(), min_dist ) )
1036  {
1037  addMarkerToPcb( fillMarker( track, text,
1039  m_currentMarker = nullptr;
1040  break;
1041  }
1042  }
1043  }
1044  }
1045 
1046  // Test pads
1047  for( unsigned ii = 0; ii < padList.size(); ii++ )
1048  {
1049  D_PAD* pad = padList[ii];
1050 
1051  if( !pad->IsOnLayer( item->GetLayer() ) )
1052  continue;
1053 
1054  wxPoint shape_pos = pad->ShapePos();
1055 
1056  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1057  {
1058  /* In order to make some calculations more easier or faster,
1059  * pads and tracks coordinates will be made relative
1060  * to the segment origin
1061  */
1062  wxPoint origin = textShape[jj]; // origin will be the origin of other coordinates
1063  m_segmEnd = textShape[jj+1] - origin;
1065  m_segmAngle = 0;
1066 
1067  // for a non horizontal or vertical segment Compute the segment angle
1068  // in tenths of degrees and its length
1069  if( delta.x || delta.y ) // delta.x == delta.y == 0 for vias
1070  {
1071  // Compute the segment angle in 0,1 degrees
1072  m_segmAngle = ArcTangente( delta.y, delta.x );
1073 
1074  // Compute the segment length: we build an equivalent rotated segment,
1075  // this segment is horizontal, therefore dx = length
1076  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
1077  }
1078 
1079  m_segmLength = delta.x;
1080  m_padToTestPos = shape_pos - origin;
1081 
1082  if( !checkClearanceSegmToPad( pad, text->GetThickness(),
1083  pad->GetClearance(NULL) ) )
1084  {
1085  addMarkerToPcb( fillMarker( pad, text,
1087  m_currentMarker = nullptr;
1088  break;
1089  }
1090  }
1091  }
1092  }
1093 }
#define DRCE_TRACK_INSIDE_TEXT
Track in inside a text area.
Definition: drc.h:85
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:204
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
wxPoint m_padToTestPos
Definition: drc.h:195
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:215
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:196
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:554
wxPoint ShapePos() const
Definition: class_pad.cpp:508
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:248
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:654
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
double m_segmAngle
Definition: drc.h:203
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:254
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 794 of file drc.cpp.

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

Referenced by RunTests().

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

Definition at line 853 of file drc.cpp.

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

Referenced by ListUnconnectedPads(), and RunTests().

854 {
855 
856  auto connectivity = m_pcb->GetConnectivity();
857 
858  connectivity->Clear();
859  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
860  connectivity->RecalculateRatsnest();
861 
862  std::vector<CN_EDGE> edges;
863  connectivity->GetUnconnectedEdges( edges );
864 
865  for( const auto& edge : edges )
866  {
867  auto src = edge.GetSourcePos();
868  auto dst = edge.GetTargetPos();
869 
870  m_unconnected.emplace_back( new DRC_ITEM( m_pcbEditorFrame->GetUserUnits(),
872  edge.GetSourceNode()->Parent(),
873  wxPoint( src.x, src.y ),
874  edge.GetTargetNode()->Parent(),
875  wxPoint( dst.x, dst.y ) ) );
876 
877  }
878 }
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item. ...
Definition: drc_item.h:48
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc.h:45
BOARD * m_pcb
Definition: drc.h:215
EDA_UNITS_T GetUserUnits() const override
Function GetUserUnits returns the user units currently in use.
Definition: draw_frame.h:268
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc.h:219
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:295
void DRC::testZones ( )
private

Definition at line 881 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::GetPosition(), ZONE_CONTAINER::IsOnCopperLayer(), m_currentMarker, m_pcb, and TestZoneToZoneOutline().

Referenced by RunTests().

882 {
883  // Test copper areas for valid netcodes
884  // if a netcode is < 0 the netname was not found when reading a netlist
885  // if a netcode is == 0 the netname is void, and the zone is not connected.
886  // This is allowed, but i am not sure this is a good idea
887  //
888  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
889  // is stored, and initialized from the file or the zone properties editor.
890  // if it differs from the net name from net code, there is a DRC issue
891  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
892  {
893  ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
894 
895  if( !test_area->IsOnCopperLayer() )
896  continue;
897 
898  int netcode = test_area->GetNetCode();
899 
900  // a netcode < 0 or > 0 and no pad in net is a error or strange
901  // perhaps a "dead" net, which happens when all pads in this net were removed
902  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
903  int pads_in_net = (test_area->GetNetCode() > 0) ?
904  m_pcb->GetConnectivity()->GetPadCount( test_area->GetNetCode() ) : 1;
905 
906  if( ( netcode < 0 ) || pads_in_net == 0 )
907  {
908  addMarkerToPcb( fillMarker( test_area, test_area->GetPosition(),
910  m_currentMarker = nullptr;
911  }
912  }
913 
914  // Test copper areas outlines, and create markers when needed
915  TestZoneToZoneOutline( NULL, true );
916 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
int TestZoneToZoneOutline(ZONE_CONTAINER *aZone, bool aCreateMarkers)
Tests whether distance between zones complies with the DRC rules.
Definition: drc.cpp:206
const wxPoint GetPosition() const override
Function GetPosition.
Definition: class_zone.cpp:169
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:67
BOARD * m_pcb
Definition: drc.h:215
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:1017
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:988
MARKER_PCB * fillMarker(TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker Optionally creates a marker and fills it in with information, but does not add it...
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:295
int DRC::TestZoneToZoneOutline ( ZONE_CONTAINER aZone,
bool  aCreateMarkers 
)

Tests whether distance between zones complies with the DRC rules.

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

Definition at line 206 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(), EDA_DRAW_FRAME::GetUserUnits(), 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().

207 {
208  BOARD* board = m_pcbEditorFrame->GetBoard();
210  BOARD_COMMIT commit( m_pcbEditorFrame );
211  int nerrors = 0;
212 
213  // iterate through all areas
214  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
215  {
216  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
217  SHAPE_POLY_SET refSmoothedPoly;
218 
219  zoneRef->BuildSmoothedPoly( refSmoothedPoly );
220 
221  if( !zoneRef->IsOnCopperLayer() )
222  continue;
223 
224  // When testing only a single area, skip all others
225  if( aZone && ( aZone != zoneRef) )
226  continue;
227 
228  for( int ia2 = 0; ia2 < board->GetAreaCount(); ia2++ )
229  {
230  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
231  SHAPE_POLY_SET testSmoothedPoly;
232 
233  zoneToTest->BuildSmoothedPoly( testSmoothedPoly );
234 
235  if( zoneRef == zoneToTest )
236  continue;
237 
238  // test for same layer
239  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
240  continue;
241 
242  // Test for same net
243  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
244  continue;
245 
246  // test for different priorities
247  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
248  continue;
249 
250  // test for different types
251  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
252  continue;
253 
254  // Examine a candidate zone: compare zoneToTest to zoneRef
255 
256  // Get clearance used in zone to zone test. The policy used to
257  // obtain that value is now part of the zone object itself by way of
258  // ZONE_CONTAINER::GetClearance().
259  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
260 
261  // Keepout areas have no clearance, so set zone2zoneClearance to 1
262  // ( zone2zoneClearance = 0 can create problems in test functions)
263  if( zoneRef->GetIsKeepout() )
264  zone2zoneClearance = 1;
265 
266  // test for some corners of zoneRef inside zoneToTest
267  for( auto iterator = refSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
268  {
269  VECTOR2I currentVertex = *iterator;
270 
271  if( testSmoothedPoly.Contains( currentVertex ) )
272  {
273  // COPPERAREA_COPPERAREA error: copper area ref corner inside copper area
274  if( aCreateMarkers )
275  {
276  wxPoint pt( currentVertex.x, currentVertex.y );
277  auto marker = new MARKER_PCB( units, COPPERAREA_INSIDE_COPPERAREA,
278  pt, zoneRef, pt, zoneToTest, pt );
279  commit.Add( marker );
280  }
281 
282  nerrors++;
283  }
284  }
285 
286  // test for some corners of zoneToTest inside zoneRef
287  for( auto iterator = testSmoothedPoly.IterateWithHoles(); iterator; iterator++ )
288  {
289  VECTOR2I currentVertex = *iterator;
290 
291  if( refSmoothedPoly.Contains( currentVertex ) )
292  {
293  // COPPERAREA_COPPERAREA error: copper area corner inside copper area ref
294  if( aCreateMarkers )
295  {
296  wxPoint pt( currentVertex.x, currentVertex.y );
297  auto marker = new MARKER_PCB( units, COPPERAREA_INSIDE_COPPERAREA,
298  pt, zoneToTest, pt, zoneRef, pt );
299  commit.Add( marker );
300  }
301 
302  nerrors++;
303  }
304  }
305 
306  // Iterate through all the segments of refSmoothedPoly
307  for( auto refIt = refSmoothedPoly.IterateSegmentsWithHoles(); refIt; refIt++ )
308  {
309  // Build ref segment
310  SEG refSegment = *refIt;
311 
312  // Iterate through all the segments in testSmoothedPoly
313  for( auto testIt = testSmoothedPoly.IterateSegmentsWithHoles(); testIt; testIt++ )
314  {
315  // Build test segment
316  SEG testSegment = *testIt;
317  wxPoint pt;
318 
319  int ax1, ay1, ax2, ay2;
320  ax1 = refSegment.A.x;
321  ay1 = refSegment.A.y;
322  ax2 = refSegment.B.x;
323  ay2 = refSegment.B.y;
324 
325  int bx1, by1, bx2, by2;
326  bx1 = testSegment.A.x;
327  by1 = testSegment.A.y;
328  bx2 = testSegment.B.x;
329  by2 = testSegment.B.y;
330 
331  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
332  0,
333  ax1, ay1, ax2, ay2,
334  0,
335  zone2zoneClearance,
336  &pt.x, &pt.y );
337 
338  if( d < zone2zoneClearance )
339  {
340  // COPPERAREA_COPPERAREA error : intersect or too close
341  if( aCreateMarkers )
342  {
343  auto marker = new MARKER_PCB( units, COPPERAREA_CLOSE_TO_COPPERAREA,
344  pt, zoneRef, pt, zoneToTest, pt );
345  commit.Add( marker );
346  }
347 
348  nerrors++;
349  }
350  }
351  }
352  }
353  }
354 
355  if( aCreateMarkers )
356  commit.Push( wxEmptyString, false, false );
357 
358  return nerrors;
359 }
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)
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.
EDA_UNITS_T GetUserUnits() const override
Function GetUserUnits returns the user units currently in use.
Definition: draw_frame.h:268
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1017
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
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:988
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
EDA_UNITS_T
Definition: common.h:159
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 545 of file drc.cpp.

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

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

546 {
547  // update my pointers, m_pcbEditorFrame is the only unchangeable one
549 
550  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
551  {
556 
558  }
559 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc.h:216
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:692
BOARD * GetBoard() const
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc.h:215
void SetList(EDA_UNITS_T aUnits, DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
DRCLISTBOX * m_ClearanceListBox
Class DRC_LIST_MARKERS is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD i...
EDA_UNITS_T GetUserUnits() const override
Function GetUserUnits returns the user units currently in use.
Definition: draw_frame.h:268
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc.h:214
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:219

Friends And Related Function Documentation

friend class DIALOG_DRC_CONTROL
friend

Definition at line 166 of file drc.h.

Referenced by ShowDRCDialog().

Member Data Documentation

bool DRC::m_doCreateRptFile
private

Definition at line 175 of file drc.h.

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

bool DRC::m_doKeepoutTest
private

Definition at line 174 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doPad2PadTest
private

Definition at line 171 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doUnconnectedTest
private

Definition at line 172 of file drc.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doZonesTest
private

Definition at line 173 of file drc.h.

Referenced by DRC().

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 216 of file drc.h.

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

bool DRC::m_drcInLegacyRoutingMode
private

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

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

Definition at line 189 of file drc.h.

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

wxPoint DRC::m_padToTestPos
private

Definition at line 195 of file drc.h.

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

PCB_EDIT_FRAME* DRC::m_pcbEditorFrame
private
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(), DRC(), DrcOnCreatingTrack(), and DrcOnCreatingZone().

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

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

wxPoint DRC::m_segmEnd
private

Definition at line 196 of file drc.h.

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

int DRC::m_segmLength
private

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

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

EDA_UNITS_T DRC::m_units
private

Definition at line 217 of file drc.h.

Referenced by DRC(), and fillMarker().

int DRC::m_xcliphi
private

Definition at line 211 of file drc.h.

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

int DRC::m_xcliplo
private

Definition at line 209 of file drc.h.

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

int DRC::m_ycliphi
private

Definition at line 212 of file drc.h.

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

int DRC::m_ycliplo
private

Definition at line 210 of file drc.h.

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


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