KiCad PCB EDA Suite
DRC Class Reference

Class DRC is the Design Rule Checker, and performs all the DRC tests. More...

#include <drc_stuff.h>

Public Member Functions

 DRC (PCB_EDIT_FRAME *aPcbWindow)
 
 ~DRC ()
 
int Drc (TRACK *aRefSeg, TRACK *aList)
 Function Drc tests the current segment and returns the result and displays the error in the status panel only if one exists. More...
 
int Drc (ZONE_CONTAINER *aArea, int aCornerIndex)
 Function Drc tests the outline segment starting at CornerIndex and returns the result and displays the error in the status panel only if one exists. More...
 
int DrcBlind (TRACK *aRefSeg, TRACK *aList)
 Function DrcBlind tests the current segment and returns the result. More...
 
void ShowDRCDialog (wxWindow *aParent=NULL)
 Function ShowDRCDialog opens 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)
 Function DestroyDRCDialog 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 aCourtyardTest, bool aCourtyardMissingTest, const wxString &aReportName, bool aSaveReport)
 Function SetSettings saves all the UI or test settings and may be called before running the tests. More...
 
void RunTests (wxTextCtrl *aMessages=NULL)
 Function RunTests will actually run all the tests specified with a previous call to SetSettings() More...
 
void ListUnconnectedPads ()
 Function ListUnconnectedPad gathers 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 ()
 Function updatePointers is a private helper function used to update needed pointers from the one pointer which is known not to change, m_pcbEditorFrame. More...
 
MARKER_PCBfillMarker (const 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 (ZONE_CONTAINER *aArea, int aErrorCode, MARKER_PCB *fillMe)
 
MARKER_PCBfillMarker (const wxPoint &aPos, int aErrorCode, const wxString &aMessage, MARKER_PCB *fillMe)
 
MARKER_PCBfillMarker (const ZONE_CONTAINER *aArea, const wxPoint &aPos, int aErrorCode, MARKER_PCB *fillMe)
 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)
 Function fillMarker fills a MARKER which will report on a generic problem with the board which is not geographically locatable. More...
 
void addMarkerToPcb (MARKER_PCB *aMarker)
 Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism. More...
 
bool testNetClasses ()
 Function testNetClasses goes 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)
 Function testTracks performs the DRC on all tracks. More...
 
void testPad2Pad ()
 
void testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testTexts ()
 
bool doNetClass (std::shared_ptr< NETCLASS > aNetClass, wxString &msg)
 
bool doPadToPadsDrc (D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
 Function doPadToPadsDrc tests the clearance between aRefPad and other pads. More...
 
bool doTrackDrc (TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
 Function DoTrackDrc tests the current segment. More...
 
bool doTrackKeepoutDrc (TRACK *aRefSeg)
 Function doTrackKeepoutDrc tests the current segment or via. More...
 
bool doEdgeZoneDrc (ZONE_CONTAINER *aArea, int aCornerIndex)
 Function doEdgeZoneDrc tests a segment in ZONE_CONTAINER * aArea: Test Edge inside other areas Test Edge too close other areas. More...
 
bool doFootprintOverlappingDrc ()
 Function doFootprintOverlappingDrc tests for footprint courtyard overlaps. More...
 
bool checkClearancePadToPad (D_PAD *aRefPad, D_PAD *aPad)
 Function checkClearancePadToPad. More...
 
bool checkClearanceSegmToPad (const D_PAD *aPad, int aSegmentWidth, int aMinDist)
 Function checkClearanceSegmToPad 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)
 Helper function checkMarginToCircle Check the distance from a point to a segment. More...
 

Private Attributes

bool m_doPad2PadTest
 
bool m_doUnconnectedTest
 
bool m_doZonesTest
 
bool m_doKeepoutTest
 
bool m_doCreateRptFile
 
bool m_doFootprintOverlapping
 
bool m_doNoCourtyardDefined
 
wxString m_rptFilename
 
MARKER_PCBm_currentMarker
 
bool m_abortDRC
 
bool m_drcInProgress
 
wxPoint m_padToTestPos
 
wxPoint m_segmEnd
 
double m_segmAngle
 
int m_segmLength
 
int m_xcliplo
 
int m_ycliplo
 
int m_xcliphi
 
int m_ycliphi
 
PCB_EDIT_FRAMEm_pcbEditorFrame
 The pcb frame editor which owns the board. More...
 
BOARDm_pcb
 
DIALOG_DRC_CONTROLm_drcDialog
 
DRC_LIST m_unconnected
 list of unconnected pads, as DRC_ITEMs More...
 

Friends

class DIALOG_DRC_CONTROL
 

Detailed Description

Class DRC is the Design Rule Checker, and 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 158 of file drc_stuff.h.

Constructor & Destructor Documentation

DRC::DRC ( PCB_EDIT_FRAME aPcbWindow)

Definition at line 115 of file drc.cpp.

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

116 {
117  m_pcbEditorFrame = aPcbWindow;
118  m_pcb = aPcbWindow->GetBoard();
119  m_drcDialog = NULL;
120 
121  // establish initial values for everything:
122  m_doPad2PadTest = true; // enable pad to pad clearance tests
123  m_doUnconnectedTest = true; // enable unconnected tests
124  m_doZonesTest = true; // enable zone to items clearance tests
125  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
126  m_doFootprintOverlapping = true; // enable courtyards areas overlap tests
127  m_doNoCourtyardDefined = true; // enable missing courtyard in footprint warning
128  m_abortDRC = false;
129  m_drcInProgress = false;
130 
131  m_doCreateRptFile = false;
132 
133  // m_rptFilename set to empty by its constructor
134 
135  m_currentMarker = NULL;
136 
137  m_segmAngle = 0;
138  m_segmLength = 0;
139 
140  m_xcliplo = 0;
141  m_ycliplo = 0;
142  m_xcliphi = 0;
143  m_ycliphi = 0;
144 }
bool m_doNoCourtyardDefined
Definition: drc_stuff.h:172
bool m_doCreateRptFile
Definition: drc_stuff.h:170
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc_stuff.h:206
int m_ycliplo
Definition: drc_stuff.h:200
int m_ycliphi
Definition: drc_stuff.h:202
int m_segmLength
Definition: drc_stuff.h:194
BOARD * GetBoard() const
BOARD * m_pcb
Definition: drc_stuff.h:205
bool m_doFootprintOverlapping
Definition: drc_stuff.h:171
bool m_doKeepoutTest
Definition: drc_stuff.h:169
bool m_doZonesTest
Definition: drc_stuff.h:168
bool m_abortDRC
Definition: drc_stuff.h:178
bool m_drcInProgress
Definition: drc_stuff.h:179
int m_xcliphi
Definition: drc_stuff.h:201
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
bool m_doPad2PadTest
Definition: drc_stuff.h:166
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
int m_xcliplo
Definition: drc_stuff.h:199
bool m_doUnconnectedTest
Definition: drc_stuff.h:167
double m_segmAngle
Definition: drc_stuff.h:193
DRC::~DRC ( )

Definition at line 147 of file drc.cpp.

References m_unconnected.

148 {
149  // maybe someday look at pointainer.h <- google for "pointainer.h"
150  for( unsigned i = 0; i<m_unconnected.size(); ++i )
151  delete m_unconnected[i];
152 }
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc_stuff.h:208

Member Function Documentation

void DRC::addMarkerToPcb ( MARKER_PCB aMarker)
private

Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.

Definition at line 92 of file drc.cpp.

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

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

93 {
94  BOARD_COMMIT commit ( m_pcbEditorFrame );
95  commit.Add( aMarker );
96  commit.Push( wxEmptyString, false );
97 }
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
bool DRC::checkClearancePadToPad ( D_PAD aRefPad,
D_PAD aPad 
)
private

Function checkClearancePadToPad.

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

593 {
594  int dist;
595  double pad_angle;
596 
597  // Get the clearance between the 2 pads. this is the min distance between aRefPad and aPad
598  int dist_min = aRefPad->GetClearance( aPad );
599 
600  // relativePadPos is the aPad shape position relative to the aRefPad shape position
601  wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos();
602 
603  dist = KiROUND( EuclideanNorm( relativePadPos ) );
604 
605  // Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
606  int delta = dist - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius();
607 
608  if( delta >= dist_min )
609  return true;
610 
611  /* Here, pads are near and DRC depend on the pad shapes
612  * We must compare distance using a fine shape analysis
613  * Because a circle or oval shape is the easier shape to test, try to have
614  * aRefPad shape type = PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
615  * if aRefPad = TRAP. and aPad = RECT, also swap pads
616  * Swap aRefPad and aPad if needed
617  */
618  bool swap_pads;
619  swap_pads = false;
620 
621  // swap pads to make comparisons easier
622  // Note also a ROUNDRECT pad with a corner radius = r can be considered as
623  // a smaller RECT (size - 2*r) with a clearance increased by r
624  // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
625  if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
626  {
627  // pad ref shape is here oval, rect, roundrect, trapezoid or custom
628  switch( aPad->GetShape() )
629  {
630  case PAD_SHAPE_CIRCLE:
631  swap_pads = true;
632  break;
633 
634  case PAD_SHAPE_OVAL:
635  swap_pads = true;
636  break;
637 
638  case PAD_SHAPE_RECT:
639  case PAD_SHAPE_ROUNDRECT:
640  if( aRefPad->GetShape() != PAD_SHAPE_OVAL )
641  swap_pads = true;
642  break;
643 
644  case PAD_SHAPE_TRAPEZOID:
645  case PAD_SHAPE_CUSTOM:
646  break;
647  }
648  }
649 
650  if( swap_pads )
651  {
652  std::swap( aRefPad, aPad );
653  relativePadPos = -relativePadPos;
654  }
655 
656  // corners of aRefPad (used only for rect/roundrect/trap pad)
657  wxPoint polyref[4];
658  // corners of aRefPad (used only for custom pad)
659  SHAPE_POLY_SET polysetref;
660 
661  // corners of aPad (used only for rect/roundrect/trap pad)
662  wxPoint polycompare[4];
663  // corners of aPad (used only custom pad)
664  SHAPE_POLY_SET polysetcompare;
665 
666  /* Because pad exchange, aRefPad shape is PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL,
667  * if one of the 2 pads was a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
668  * Therefore, if aRefPad is a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID,
669  * aPad is also a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID
670  */
671  bool diag = true;
672 
673  switch( aRefPad->GetShape() )
674  {
675  case PAD_SHAPE_CIRCLE:
676 
677  /* One can use checkClearanceSegmToPad to test clearance
678  * aRefPad is like a track segment with a null length and a witdth = GetSize().x
679  */
680  m_segmLength = 0;
681  m_segmAngle = 0;
682 
683  m_segmEnd.x = m_segmEnd.y = 0;
684 
685  m_padToTestPos = relativePadPos;
686  diag = checkClearanceSegmToPad( aPad, aRefPad->GetSize().x, dist_min );
687  break;
688 
689  case PAD_SHAPE_TRAPEZOID:
690  case PAD_SHAPE_ROUNDRECT:
691  case PAD_SHAPE_RECT:
692  case PAD_SHAPE_CUSTOM:
693  // pad_angle = pad orient relative to the aRefPad orient
694  pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
695  NORMALIZE_ANGLE_POS( pad_angle );
696 
697  if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
698  {
699  int padRadius = aRefPad->GetRoundRectCornerRadius();
700  dist_min += padRadius;
701  GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ),
702  aRefPad->GetSize(), aRefPad->GetOrientation() );
703  }
704  else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM )
705  {
706  polysetref.Append( aRefPad->GetCustomShapeAsPolygon() );
707 
708  // The reference pad can be rotated. calculate the rotated
709  // coordiantes ( note, the ref pad position is the origin of
710  // coordinates for this drc test)
711  aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref,
712  wxPoint( 0, 0 ), aRefPad->GetOrientation() );
713  }
714  else
715  {
716  // BuildPadPolygon has meaning for rect a trapeziod shapes
717  // and returns the 4 corners
718  aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
719  }
720 
721  switch( aPad->GetShape() )
722  {
723  case PAD_SHAPE_ROUNDRECT:
724  case PAD_SHAPE_RECT:
725  case PAD_SHAPE_TRAPEZOID:
726  case PAD_SHAPE_CUSTOM:
727  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
728  {
729  int padRadius = aPad->GetRoundRectCornerRadius();
730  dist_min += padRadius;
731  GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos,
732  aPad->GetSize(), aPad->GetOrientation() );
733  }
734  else if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
735  {
736  polysetcompare.Append( aPad->GetCustomShapeAsPolygon() );
737 
738  // The pad to compare can be rotated. calculate the rotated
739  // coordinattes ( note, the pad to compare position
740  // is the relativePadPos for this drc test
741  aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare,
742  relativePadPos, aPad->GetOrientation() );
743  }
744  else
745  {
746  aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() );
747 
748  // Move aPad shape to relativePadPos
749  for( int ii = 0; ii < 4; ii++ )
750  polycompare[ii] += relativePadPos;
751  }
752  // And now test polygons: We have 3 cases:
753  // one poly is complex and the other is basic (has only 4 corners)
754  // both polys are complex
755  // both polys are basic (have only 4 corners) the most usual case
756  if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0)
757  {
758  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
759  // And now test polygons:
760  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
761  polycompare, 4, dist_min ) )
762  diag = false;
763  }
764  else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount())
765  {
766  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
767  // And now test polygons:
768  if( !poly2polyDRC( (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(),
769  polyref, 4, dist_min ) )
770  diag = false;
771  }
772  else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() )
773  {
774  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
775  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
776 
777  // And now test polygons:
778  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
779  (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(), dist_min ) )
780  diag = false;
781  }
782  else if( !poly2polyDRC( polyref, 4, polycompare, 4, dist_min ) )
783  diag = false;
784  break;
785 
786  default:
787  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() );
788  break;
789  }
790  break;
791 
792  case PAD_SHAPE_OVAL: /* an oval pad is like a track segment */
793  {
794  /* Create a track segment with same dimensions as the oval aRefPad
795  * and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
796  */
797  int segm_width;
798  m_segmAngle = aRefPad->GetOrientation(); // Segment orient.
799 
800  if( aRefPad->GetSize().y < aRefPad->GetSize().x ) // Build an horizontal equiv segment
801  {
802  segm_width = aRefPad->GetSize().y;
803  m_segmLength = aRefPad->GetSize().x - aRefPad->GetSize().y;
804  }
805  else // Vertical oval: build an horizontal equiv segment and rotate 90.0 deg
806  {
807  segm_width = aRefPad->GetSize().x;
808  m_segmLength = aRefPad->GetSize().y - aRefPad->GetSize().x;
809  m_segmAngle += 900;
810  }
811 
812  /* the start point must be 0,0 and currently relativePadPos
813  * is relative the center of pad coordinate */
814  wxPoint segstart;
815  segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
816 
817  RotatePoint( &segstart, m_segmAngle ); // actual start point coordinate of the equivalent segment
818  // Calculate segment end position relative to the segment origin
819  m_segmEnd.x = -2 * segstart.x;
820  m_segmEnd.y = -2 * segstart.y;
821 
822  // Recalculate the equivalent segment angle in 0,1 degrees
823  // to prepare a call to checkClearanceSegmToPad()
825 
826  // move pad position relative to the segment origin
827  m_padToTestPos = relativePadPos - segstart;
828 
829  // Use segment to pad check to test the second pad:
830  diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
831  break;
832  }
833 
834  default:
835  wxMessageBox( wxT( "DRC::checkClearancePadToPad: unknown pad shape" ) );
836  break;
837  }
838 
839  return diag;
840 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
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:511
static const int dist[10][10]
Definition: dist.cpp:57
int m_segmLength
Definition: drc_stuff.h:194
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
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_stuff.h:185
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:271
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:586
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)
Function checkClearanceSegmToPad check the distance from a pad to segment.
wxPoint m_segmEnd
Definition: drc_stuff.h:186
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:375
bool poly2polyDRC(wxPoint *aTref, int aTrefCount, wxPoint *aTcompare, int aTcompareCount, int aDist)
DRC control: these functions make a DRC between pads, tracks and pads versus tracks.
void GetRoundRectCornerCenters(wxPoint aCenters[4], int aRadius, const wxPoint &aPosition, const wxSize &aSize, double aRotation)
Helper function GetRoundRectCornerCenters Has meaning only for rounded rect Returns the centers of th...
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:546
wxPoint ShapePos() const
Definition: class_pad.cpp:500
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
double m_segmAngle
Definition: drc_stuff.h:193
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

Function checkClearanceSegmToPad 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 848 of file drc_clearance_test_functions.cpp.

References abs, AddAngles(), SHAPE_POLY_SET::Append(), D_PAD::BuildPadPolygon(), checkLine(), checkMarginToCircle(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), D_PAD::CustomShapeAsPolygonToBoardPosition(), 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, 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().

849 {
850  // Note:
851  // we are using a horizontal segment for test, because we know here
852  // only the length and orientation+ of the segment
853  // Therefore the coordinates of the shape of pad to compare
854  // must be calculated in a axis system rotated by m_segmAngle
855  // and centered to the segment origin, before they can be tested
856  // against the segment
857  // We are using:
858  // m_padToTestPos the position of the pad shape in this axis system
859  // m_segmAngle the axis system rotation
860 
861  int segmHalfWidth = aSegmentWidth / 2;
862  int distToLine = segmHalfWidth + aMinDist;
863 
864  wxSize padHalfsize; // half dimension of the pad
865 
866  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
867  {
868  // For a custom pad, the pad size has no meaning, we only can
869  // use the bounding radius
870  padHalfsize.x = padHalfsize.y = aPad->GetBoundingRadius();
871  }
872  else
873  {
874  padHalfsize.x = aPad->GetSize().x >> 1;
875  padHalfsize.y = aPad->GetSize().y >> 1;
876  }
877 
878  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
879  {
880  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
881  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
882  }
883 
884  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
885  {
886  /* Easy case: just test the distance between segment and pad centre
887  * calculate pad coordinates in the X,Y axis with X axis = segment to test
888  */
890  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
891  }
892 
893  /* calculate the bounding box of the pad, including the clearance and the segment width
894  * if the line from 0 to m_segmEnd does not intersect this bounding box,
895  * the clearance is always OK
896  * But if intersect, a better analysis of the pad shape must be done.
897  */
898  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
899  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
900  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
901  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
902 
903  wxPoint startPoint;
904  wxPoint endPoint = m_segmEnd;
905 
906  double orient = aPad->GetOrientation();
907 
908  RotatePoint( &startPoint, m_padToTestPos, -orient );
909  RotatePoint( &endPoint, m_padToTestPos, -orient );
910 
911  if( checkLine( startPoint, endPoint ) )
912  return true;
913 
914  /* segment intersects the bounding box. But there is not always a DRC error.
915  * A fine analysis of the pad shape must be done.
916  */
917  switch( aPad->GetShape() )
918  {
919  case PAD_SHAPE_CIRCLE:
920  // This case was already tested, so it cannot be found here.
921  // it is here just to avoid compil warning, and to remember
922  // it is already tested.
923  return false;
924 
925  case PAD_SHAPE_OVAL:
926  {
927  /* an oval is a complex shape, but is a rectangle and 2 circles
928  * these 3 basic shapes are more easy to test.
929  *
930  * In calculations we are using a vertical oval shape
931  * (i.e. a vertical rounded segment)
932  * for horizontal oval shapes, swap x and y size and rotate the shape
933  */
934  if( padHalfsize.x > padHalfsize.y )
935  {
936  std::swap( padHalfsize.x, padHalfsize.y );
937  orient = AddAngles( orient, 900 );
938  }
939 
940  // here, padHalfsize.x is the radius of rounded ends.
941 
942  int deltay = padHalfsize.y - padHalfsize.x;
943  // here: padHalfsize.x = radius,
944  // deltay = dist between the centre pad and the centre of a rounded end
945 
946  // Test the rectangular area between the two circles (the rounded ends)
947  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
948  m_ycliplo = m_padToTestPos.y - deltay;
949  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
950  m_ycliphi = m_padToTestPos.y + deltay;
951 
952  if( !checkLine( startPoint, endPoint ) )
953  {
954  return false;
955  }
956 
957  // test the first circle
958  startPoint.x = m_padToTestPos.x; // startPoint = centre of the upper circle of the oval shape
959  startPoint.y = m_padToTestPos.y + deltay;
960 
961  // Calculate the actual position of the circle, given the pad orientation:
962  RotatePoint( &startPoint, m_padToTestPos, orient );
963 
964  // Calculate the actual position of the circle in the new X,Y axis:
965  RotatePoint( &startPoint, m_segmAngle );
966 
967  if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
968  {
969  return false;
970  }
971 
972  // test the second circle
973  startPoint.x = m_padToTestPos.x; // startPoint = centre of the lower circle of the oval shape
974  startPoint.y = m_padToTestPos.y - deltay;
975  RotatePoint( &startPoint, m_padToTestPos, orient );
976  RotatePoint( &startPoint, m_segmAngle );
977 
978  if( !checkMarginToCircle( startPoint, padHalfsize.x + distToLine, m_segmLength ) )
979  {
980  return false;
981  }
982  }
983  break;
984 
985  case PAD_SHAPE_ROUNDRECT:
986  {
987  // a round rect is a smaller rect, with a clearance augmented by the corners radius
988  int r = aPad->GetRoundRectCornerRadius();
989  padHalfsize.x -= r;
990  padHalfsize.y -= r;
991  distToLine += r;
992  }
993  // Fall through
994  case PAD_SHAPE_RECT:
995  // the area to test is a rounded rectangle.
996  // this can be done by testing 2 rectangles and 4 circles (the corners)
997 
998  // Testing the first rectangle dimx + distToLine, dimy:
999  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
1000  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
1001  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
1002  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
1003 
1004  if( !checkLine( startPoint, endPoint ) )
1005  return false;
1006 
1007  // Testing the second rectangle dimx , dimy + distToLine
1008  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
1009  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
1010  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
1011  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
1012 
1013  if( !checkLine( startPoint, endPoint ) )
1014  return false;
1015 
1016  // testing the 4 circles which are the clearance area of each corner:
1017 
1018  // testing the left top corner of the rectangle
1019  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1020  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1021  RotatePoint( &startPoint, m_padToTestPos, orient );
1022  RotatePoint( &startPoint, m_segmAngle );
1023 
1024  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1025  return false;
1026 
1027  // testing the right top corner of the rectangle
1028  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1029  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1030  RotatePoint( &startPoint, m_padToTestPos, orient );
1031  RotatePoint( &startPoint, m_segmAngle );
1032 
1033  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1034  return false;
1035 
1036  // testing the left bottom corner of the rectangle
1037  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1038  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1039  RotatePoint( &startPoint, m_padToTestPos, orient );
1040  RotatePoint( &startPoint, m_segmAngle );
1041 
1042  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1043  return false;
1044 
1045  // testing the right bottom corner of the rectangle
1046  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1047  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1048  RotatePoint( &startPoint, m_padToTestPos, orient );
1049  RotatePoint( &startPoint, m_segmAngle );
1050 
1051  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1052  return false;
1053 
1054  break;
1055 
1056  case PAD_SHAPE_TRAPEZOID:
1057  {
1058  wxPoint poly[4];
1059  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
1060 
1061  // Move shape to m_padToTestPos
1062  for( int ii = 0; ii < 4; ii++ )
1063  {
1064  poly[ii] += m_padToTestPos;
1065  RotatePoint( &poly[ii], m_segmAngle );
1066  }
1067 
1068  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ),
1069  wxPoint(m_segmLength,0), distToLine ) )
1070  return false;
1071  }
1072  break;
1073 
1074  case PAD_SHAPE_CUSTOM:
1075  {
1076  SHAPE_POLY_SET polyset;
1077  polyset.Append( aPad->GetCustomShapeAsPolygon() );
1078  // The pad can be rotated. calculate the coordinates
1079  // relatives to the segment being tested
1080  // Note, the pad position relative to the segment origin
1081  // is m_padToTestPos
1082  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1083  m_padToTestPos, orient );
1084 
1085  // Rotate all coordinates by m_segmAngle, because the segment orient
1086  // is m_segmAngle
1087  // we are using a horizontal segment for test, because we know here
1088  // only the lenght and orientation+ of the segment
1089  // therefore all coordinates of the pad to test must be rotated by
1090  // m_segmAngle (they are already relative to the segment origin)
1091  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1092  wxPoint( 0, 0 ), m_segmAngle );
1093 
1094  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1095 
1096  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1097  refpoly.PointCount(),
1098  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1099  distToLine ) )
1100  return false;
1101  }
1102  break;
1103  }
1104 
1105  return true;
1106 }
int m_ycliplo
Definition: drc_stuff.h:200
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:511
int m_ycliphi
Definition: drc_stuff.h:202
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc_stuff.h:194
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
wxPoint m_padToTestPos
Definition: drc_stuff.h:185
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:216
#define abs(a)
Definition: auxiliary.h:84
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...
T AddAngles(T a1, T2 a2)
Add two angles (keeping the result normalized). T2 is here.
Definition: trigo.h:267
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:586
Class SHAPE_POLY_SET.
const wxSize & GetSize() const
Definition: class_pad.h:269
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Helper function checkMarginToCircle Check the distance from a point to a segment. ...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
int m_xcliphi
Definition: drc_stuff.h:201
wxPoint m_segmEnd
Definition: drc_stuff.h:186
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:375
const wxSize & GetDelta() const
Definition: class_pad.h:272
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
int m_xcliplo
Definition: drc_stuff.h:199
double m_segmAngle
Definition: drc_stuff.h:193
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 1153 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().

1154 {
1155 #define WHEN_OUTSIDE return true
1156 #define WHEN_INSIDE
1157  int temp;
1158 
1159  if( aSegStart.x > aSegEnd.x )
1160  std::swap( aSegStart, aSegEnd );
1161 
1162  if( (aSegEnd.x < m_xcliplo) || (aSegStart.x > m_xcliphi) )
1163  {
1164  WHEN_OUTSIDE;
1165  }
1166 
1167  if( aSegStart.y < aSegEnd.y )
1168  {
1169  if( (aSegEnd.y < m_ycliplo) || (aSegStart.y > m_ycliphi) )
1170  {
1171  WHEN_OUTSIDE;
1172  }
1173 
1174  if( aSegStart.y < m_ycliplo )
1175  {
1176  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegStart.y),
1177  (aSegEnd.y - aSegStart.y) );
1178 
1179  if( (aSegStart.x += temp) > m_xcliphi )
1180  {
1181  WHEN_OUTSIDE;
1182  }
1183 
1184  aSegStart.y = m_ycliplo;
1185  WHEN_INSIDE;
1186  }
1187 
1188  if( aSegEnd.y > m_ycliphi )
1189  {
1190  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegEnd.y - m_ycliphi),
1191  (aSegEnd.y - aSegStart.y) );
1192 
1193  if( (aSegEnd.x -= temp) < m_xcliplo )
1194  {
1195  WHEN_OUTSIDE;
1196  }
1197 
1198  aSegEnd.y = m_ycliphi;
1199  WHEN_INSIDE;
1200  }
1201 
1202  if( aSegStart.x < m_xcliplo )
1203  {
1204  temp = USCALE( (aSegEnd.y - aSegStart.y), (m_xcliplo - aSegStart.x),
1205  (aSegEnd.x - aSegStart.x) );
1206  aSegStart.y += temp;
1207  aSegStart.x = m_xcliplo;
1208  WHEN_INSIDE;
1209  }
1210 
1211  if( aSegEnd.x > m_xcliphi )
1212  {
1213  temp = USCALE( (aSegEnd.y - aSegStart.y), (aSegEnd.x - m_xcliphi),
1214  (aSegEnd.x - aSegStart.x) );
1215  aSegEnd.y -= temp;
1216  aSegEnd.x = m_xcliphi;
1217  WHEN_INSIDE;
1218  }
1219  }
1220  else
1221  {
1222  if( (aSegStart.y < m_ycliplo) || (aSegEnd.y > m_ycliphi) )
1223  {
1224  WHEN_OUTSIDE;
1225  }
1226 
1227  if( aSegStart.y > m_ycliphi )
1228  {
1229  temp = USCALE( (aSegEnd.x - aSegStart.x), (aSegStart.y - m_ycliphi),
1230  (aSegStart.y - aSegEnd.y) );
1231 
1232  if( (aSegStart.x += temp) > m_xcliphi )
1233  {
1234  WHEN_OUTSIDE;
1235  }
1236 
1237  aSegStart.y = m_ycliphi;
1238  WHEN_INSIDE;
1239  }
1240 
1241  if( aSegEnd.y < m_ycliplo )
1242  {
1243  temp = USCALE( (aSegEnd.x - aSegStart.x), (m_ycliplo - aSegEnd.y),
1244  (aSegStart.y - aSegEnd.y) );
1245 
1246  if( (aSegEnd.x -= temp) < m_xcliplo )
1247  {
1248  WHEN_OUTSIDE;
1249  }
1250 
1251  aSegEnd.y = m_ycliplo;
1252  WHEN_INSIDE;
1253  }
1254 
1255  if( aSegStart.x < m_xcliplo )
1256  {
1257  temp = USCALE( (aSegStart.y - aSegEnd.y), (m_xcliplo - aSegStart.x),
1258  (aSegEnd.x - aSegStart.x) );
1259  aSegStart.y -= temp;
1260  aSegStart.x = m_xcliplo;
1261  WHEN_INSIDE;
1262  }
1263 
1264  if( aSegEnd.x > m_xcliphi )
1265  {
1266  temp = USCALE( (aSegStart.y - aSegEnd.y), (aSegEnd.x - m_xcliphi),
1267  (aSegEnd.x - aSegStart.x) );
1268  aSegEnd.y += temp;
1269  aSegEnd.x = m_xcliphi;
1270  WHEN_INSIDE;
1271  }
1272  }
1273 
1274  if( ( (aSegEnd.x + aSegStart.x) / 2 <= m_xcliphi )
1275  && ( (aSegEnd.x + aSegStart.x) / 2 >= m_xcliplo ) \
1276  && ( (aSegEnd.y + aSegStart.y) / 2 <= m_ycliphi )
1277  && ( (aSegEnd.y + aSegStart.y) / 2 >= m_ycliplo ) )
1278  {
1279  return false;
1280  }
1281  else
1282  {
1283  return true;
1284  }
1285 }
static int USCALE(unsigned arg, unsigned num, unsigned den)
#define WHEN_OUTSIDE
int m_ycliplo
Definition: drc_stuff.h:200
int m_ycliphi
Definition: drc_stuff.h:202
int m_xcliphi
Definition: drc_stuff.h:201
#define WHEN_INSIDE
int m_xcliplo
Definition: drc_stuff.h:199
bool DRC::checkMarginToCircle ( wxPoint  aCentre,
int  aRadius,
int  aLength 
)
staticprivate

Helper function checkMarginToCircle 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 1115 of file drc_clearance_test_functions.cpp.

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

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

1116 {
1117  if( abs( aCentre.y ) >= aRadius ) // trivial case
1118  return true;
1119 
1120  // Here, distance between aCentre and X axis is < aRadius
1121  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1122  {
1123  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1124  return false; // aCentre is between the starting point and the ending point of the segm
1125 
1126  if( aCentre.x > aLength ) // aCentre is after the ending point
1127  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1128 
1129  if( EuclideanNorm( aCentre ) < aRadius )
1130  // distance between aCentre and the starting point or the ending point is < aRadius
1131  return false;
1132  }
1133 
1134  return true;
1135 }
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)

Function DestroyDRCDialog 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 99 of file drc.cpp.

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

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

100 {
101  if( m_drcDialog )
102  {
103  if( aReason == wxID_OK )
104  {
105  // if user clicked OK, save his choices in this DRC object.
107  }
108 
109  m_drcDialog->Destroy();
110  m_drcDialog = NULL;
111  }
112 }
bool m_doCreateRptFile
Definition: drc_stuff.h:170
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc_stuff.h:206
void GetRptSettings(bool *aEnable, wxString &aFileName)
Definition: dialog_drc.cpp:164
wxString m_rptFilename
Definition: drc_stuff.h:174
bool DRC::doEdgeZoneDrc ( ZONE_CONTAINER aArea,
int  aCornerIndex 
)
private

Function doEdgeZoneDrc tests 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 443 of file zones_test_and_combine_areas.cpp.

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

Referenced by Drc().

444 {
445  if( !aArea->IsOnCopperLayer() ) // Cannot have a Drc error if not on copper layer
446  return true;
447  // Get polygon, contour and vertex index.
449 
450  // If the vertex does not exist, there is no conflict
451  if( !aArea->Outline()->GetRelativeIndices( aCornerIndex, &index ) )
452  return true;
453 
454  // Retrieve the selected contour
455  SHAPE_LINE_CHAIN contour;
456  contour = aArea->Outline()->Polygon( index.m_polygon )[index.m_contour];
457 
458  // Retrieve the segment that starts at aCornerIndex-th corner.
459  SEG selectedSegment = contour.Segment( index.m_vertex );
460 
461  VECTOR2I start = selectedSegment.A;
462  VECTOR2I end = selectedSegment.B;
463 
464  // iterate through all areas
465  for( int ia2 = 0; ia2 < m_pcb->GetAreaCount(); ia2++ )
466  {
467  ZONE_CONTAINER* area_to_test = m_pcb->GetArea( ia2 );
468  int zone_clearance = std::max( area_to_test->GetZoneClearance(),
469  aArea->GetZoneClearance() );
470 
471  // test for same layer
472  if( area_to_test->GetLayer() != aArea->GetLayer() )
473  continue;
474 
475  // Test for same net
476  if( ( aArea->GetNetCode() == area_to_test->GetNetCode() ) && (aArea->GetNetCode() >= 0) )
477  continue;
478 
479  // test for same priority
480  if( area_to_test->GetPriority() != aArea->GetPriority() )
481  continue;
482 
483  // test for same type
484  if( area_to_test->GetIsKeepout() != aArea->GetIsKeepout() )
485  continue;
486 
487  // For keepout, there is no clearance, so use a minimal value for it
488  // use 1, not 0 as value to avoid some issues in tests
489  if( area_to_test->GetIsKeepout() )
490  zone_clearance = 1;
491 
492  // test for ending line inside area_to_test
493  if( area_to_test->Outline()->Contains( end ) )
494  {
495  // COPPERAREA_COPPERAREA error: corner inside copper area
496  m_currentMarker = fillMarker( aArea, static_cast<wxPoint>( end ),
498  m_currentMarker );
499  return false;
500  }
501 
502  // now test spacing between areas
503  int ax1 = start.x;
504  int ay1 = start.y;
505  int ax2 = end.x;
506  int ay2 = end.y;
507 
508  // Iterate through all edges in the polygon.
510  for( iterator = area_to_test->Outline()->IterateSegmentsWithHoles(); iterator; iterator++ )
511  {
512  SEG segment = *iterator;
513 
514  int bx1 = segment.A.x;
515  int by1 = segment.A.y;
516  int bx2 = segment.B.x;
517  int by2 = segment.B.y;
518 
519  int x, y; // variables containing the intersecting point coordinates
520  int d = GetClearanceBetweenSegments( bx1, by1, bx2, by2,
521  0,
522  ax1, ay1, ax2, ay2,
523  0,
524  zone_clearance,
525  &x, &y );
526 
527  if( d < zone_clearance )
528  {
529  // COPPERAREA_COPPERAREA error : edge intersect or too close
530  m_currentMarker = fillMarker( aArea, wxPoint( x, y ),
532  m_currentMarker );
533  return false;
534  }
535 
536  }
537  }
538 
539  return true;
540 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
MARKER_PCB * fillMarker(const TRACK *aTrack, BOARD_ITEM *aItem, int aErrorCode, MARKER_PCB *fillMe)
Function fillMarker optionally creates a marker and fills it in with information, but does not add it...
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:182
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:262
#define COPPERAREA_CLOSE_TO_COPPERAREA
copper area outlines are too close
Definition: drc_stuff.h:62
Struct VERTEX_INDEX.
Class SEGMENT_ITERATOR_TEMPLATE.
int GetClearanceBetweenSegments(int x1i, int y1i, int x1f, int y1f, int w1, int x2i, int y2i, int x2f, int y2f, int w2, int max_cl, int *x, int *y)
BOARD * m_pcb
Definition: drc_stuff.h:205
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:672
bool GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Function GetRelativeIndices.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
Definition: seg.h:36
SEG Segment(int aIndex)
Function Segment()
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:188
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
VECTOR2I A
Definition: seg.h:46
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:119
int GetZoneClearance() const
Definition: class_zone.h:218
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1) const
Returns true if a given subpolygon contains the point aP.
#define COPPERAREA_INSIDE_COPPERAREA
copper area outlines intersect
Definition: drc_stuff.h:61
VECTOR2I B
Definition: seg.h:47
bool DRC::doFootprintOverlappingDrc ( )
private

Function doFootprintOverlappingDrc tests for footprint courtyard overlaps.

Returns
bool - false if DRC error or true if OK

Definition at line 977 of file drc.cpp.

References addMarkerToPcb(), SHAPE_POLY_SET::Append(), SHAPE_POLY_SET::BooleanIntersection(), DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT, DRCE_MISSING_COURTYARD_IN_FOOTPRINT, DRCE_OVERLAPPING_FOOTPRINTS, fillMarker(), m_currentMarker, m_doFootprintOverlapping, m_doNoCourtyardDefined, BOARD::m_Modules, m_pcb, MODULE::Next(), SHAPE_POLY_SET::OutlineCount(), SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::RemoveAllContours(), SHAPE_POLY_SET::Vertex(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by RunTests().

978 {
979  // Detects missing (or malformed) footprint courtyard,
980  // and for footprint with courtyard, courtyards overlap.
981  wxString msg;
982  bool success = true;
983 
984  // Update courtyard polygons, and test for missing courtyard definition:
985  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
986  {
987  bool is_ok = footprint->BuildPolyCourtyard();
988 
989  if( !is_ok && m_doFootprintOverlapping )
990  {
991  msg.Printf( _( "footprint '%s' has malformed courtyard" ),
992  footprint->GetReference().GetData() );
993  m_currentMarker = fillMarker( footprint->GetPosition(),
995  msg, m_currentMarker );
997  m_currentMarker = nullptr;
998  success = false;
999  }
1000 
1001  if( !m_doNoCourtyardDefined )
1002  continue;
1003 
1004  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 &&
1005  footprint->GetPolyCourtyardBack().OutlineCount() == 0 &&
1006  is_ok )
1007  {
1008  msg.Printf( _( "footprint '%s' has no courtyard defined" ),
1009  footprint->GetReference().GetData() );
1010  m_currentMarker = fillMarker( footprint->GetPosition(),
1012  msg, m_currentMarker );
1014  m_currentMarker = nullptr;
1015  success = false;
1016  }
1017  }
1018 
1020  return success;
1021 
1022  // Now test for overlapping on top layer:
1023  SHAPE_POLY_SET courtyard; // temporary storage of the courtyard of current footprint
1024 
1025  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1026  {
1027  if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 )
1028  continue; // No courtyard defined
1029 
1030  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1031  {
1032  if( candidate->GetPolyCourtyardFront().OutlineCount() == 0 )
1033  continue; // No courtyard defined
1034 
1035  courtyard.RemoveAllContours();
1036  courtyard.Append( footprint->GetPolyCourtyardFront() );
1037 
1038  // Build the common area between footprint and the candidate:
1039  courtyard.BooleanIntersection( candidate->GetPolyCourtyardFront(), SHAPE_POLY_SET::PM_FAST );
1040 
1041  // If no overlap, courtyard is empty (no common area).
1042  // Therefore if a common polygon exists, this is a DRC error
1043  if( courtyard.OutlineCount() )
1044  {
1045  //Overlap between footprint and candidate
1046  msg.Printf( _( "footprints '%s' and '%s' overlap on front (top) layer" ),
1047  footprint->GetReference().GetData(),
1048  candidate->GetReference().GetData() );
1049  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1050  wxPoint loc( pos.x, pos.y );
1053  m_currentMarker = nullptr;
1054  success = false;
1055  }
1056  }
1057  }
1058 
1059  // Test for overlapping on bottom layer:
1060  for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
1061  {
1062  if( footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
1063  continue; // No courtyard defined
1064 
1065  for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
1066  {
1067  if( candidate->GetPolyCourtyardBack().OutlineCount() == 0 )
1068  continue; // No courtyard defined
1069 
1070  courtyard.RemoveAllContours();
1071  courtyard.Append( footprint->GetPolyCourtyardBack() );
1072 
1073  // Build the common area between footprint and the candidate:
1074  courtyard.BooleanIntersection( candidate->GetPolyCourtyardBack(), SHAPE_POLY_SET::PM_FAST );
1075 
1076  // If no overlap, courtyard is empty (no common area).
1077  // Therefore if a common polygon exists, this is a DRC error
1078  if( courtyard.OutlineCount() )
1079  {
1080  //Overlap between footprint and candidate
1081  msg.Printf( _( "footprints '%s' and '%s' overlap on back (bottom) layer" ),
1082  footprint->GetReference().GetData(),
1083  candidate->GetReference().GetData() );
1084  VECTOR2I& pos = courtyard.Vertex( 0, 0, -1 );
1085  wxPoint loc( pos.x, pos.y );
1088  m_currentMarker = nullptr;
1089  success = false;
1090  }
1091  }
1092  }
1093 
1094  return success;
1095 }
bool m_doNoCourtyardDefined
Definition: drc_stuff.h:172
MARKER_PCB * fillMarker(const 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...
MODULE * Next() const
Definition: class_module.h:120
#define DRCE_MISSING_COURTYARD_IN_FOOTPRINT
footprint has no courtyard defined
Definition: drc_stuff.h:84
int OutlineCount() const
Returns the number of outlines in the set
BOARD * m_pcb
Definition: drc_stuff.h:205
bool m_doFootprintOverlapping
Definition: drc_stuff.h:171
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)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
Class SHAPE_POLY_SET.
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_stuff.h:176
#define DRCE_OVERLAPPING_FOOTPRINTS
footprint courtyards overlap
Definition: drc_stuff.h:83
DLIST< MODULE > m_Modules
Definition: class_board.h:245
#define DRCE_MALFORMED_COURTYARD_IN_FOOTPRINT
footprint has a courtyard but malformed
Definition: drc_stuff.h:85
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline) ...
bool DRC::doNetClass ( std::shared_ptr< NETCLASS aNetClass,
wxString &  msg 
)
private

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

340 {
341  bool ret = true;
342 
344 
345 #define FmtVal( x ) GetChars( StringFromValue( g_UserUnit, x ) )
346 
347 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
348  if( nc->GetClearance() < g.m_MinClearance )
349  {
350  msg.Printf( _( "NETCLASS: '%s' has Clearance:%s which is less than global:%s" ),
351  GetChars( nc->GetName() ),
352  FmtVal( nc->GetClearance() ),
353  FmtVal( g.m_TrackClearance )
354  );
355 
357  m_currentMarker = nullptr;
358  ret = false;
359  }
360 #endif
361 
362  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
363  {
364  msg.Printf( _( "NETCLASS: '%s' has TrackWidth:%s which is less than global:%s" ),
365  GetChars( nc->GetName() ),
366  FmtVal( nc->GetTrackWidth() ),
368  );
369 
371  m_currentMarker = nullptr;
372  ret = false;
373  }
374 
375  if( nc->GetViaDiameter() < g.m_ViasMinSize )
376  {
377  msg.Printf( _( "NETCLASS: '%s' has Via Dia:%s which is less than global:%s" ),
378  GetChars( nc->GetName() ),
379  FmtVal( nc->GetViaDiameter() ),
380  FmtVal( g.m_ViasMinSize )
381  );
382 
384  m_currentMarker = nullptr;
385  ret = false;
386  }
387 
388  if( nc->GetViaDrill() < g.m_ViasMinDrill )
389  {
390  msg.Printf( _( "NETCLASS: '%s' has Via Drill:%s which is less than global:%s" ),
391  GetChars( nc->GetName() ),
392  FmtVal( nc->GetViaDrill() ),
394  );
395 
397  m_currentMarker = nullptr;
398  ret = false;
399  }
400 
401  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
402  {
403  msg.Printf( _( "NETCLASS: '%s' has uVia Dia:%s which is less than global:%s" ),
404  GetChars( nc->GetName() ),
405  FmtVal( nc->GetuViaDiameter() ),
407  );
408 
410  m_currentMarker = nullptr;
411  ret = false;
412  }
413 
414  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
415  {
416  msg.Printf( _( "NETCLASS: '%s' has uVia Drill:%s which is less than global:%s" ),
417  GetChars( nc->GetName() ),
418  FmtVal( nc->GetuViaDrill() ),
420  );
421 
423  m_currentMarker = nullptr;
424  ret = false;
425  }
426 
427  return ret;
428 }
#define DRCE_NETCLASS_CLEARANCE
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc_stuff.h:72
MARKER_PCB * fillMarker(const 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...
BOARD * m_pcb
Definition: drc_stuff.h:205
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
#define DRCE_NETCLASS_uVIADRILLSIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc_stuff.h:76
int m_TrackMinWidth
track min value for width ((min copper size value
int m_ViasMinSize
vias (not micro vias) min diameter
int m_ViasMinDrill
vias (not micro vias) min drill diameter
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
int m_MicroViasMinSize
micro vias (not vias) min diameter
#define FmtVal(x)
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
#define DRCE_NETCLASS_uVIASIZE
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc_stuff.h:75
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
#define DRCE_NETCLASS_TRACKWIDTH
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc_stuff.h:71
#define DRCE_NETCLASS_VIASIZE
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc_stuff.h:73
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
#define DRCE_NETCLASS_VIADRILLSIZE
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc_stuff.h:74
bool DRC::doPadToPadsDrc ( D_PAD aRefPad,
D_PAD **  aStart,
D_PAD **  aEnd,
int  x_limit 
)
private

Function doPadToPadsDrc tests the clearance between aRefPad and other pads.

The pad list must be sorted by x coordinate.

Parameters
aRefPadThe pad to test
aStartThe start of the pad list to test against
aEndMarks the end of the list and is not included
x_limitis used to stop the test (when the any pad's X coord exceeds this)

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

844 {
845  const static LSET all_cu = LSET::AllCuMask();
846 
847  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
848 
849  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
850  * to test pad to pad hole DRC, using the pad to pad DRC test function.
851  * Therefore, this dummy pad is a circle or an oval.
852  * A pad must have a parent because some functions expect a non null parent
853  * to find the parent board, and some other data
854  */
855  MODULE dummymodule( m_pcb ); // Creates a dummy parent
856  D_PAD dummypad( &dummymodule );
857 
858  // Ensure the hole is on all copper layers
859  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
860 
861  // Use the minimal local clearance value for the dummy pad.
862  // The clearance of the active pad will be used as minimum distance to a hole
863  // (a value = 0 means use netclass value)
864  dummypad.SetLocalClearance( 1 );
865 
866  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
867  {
868  D_PAD* pad = *pad_list;
869 
870  if( pad == aRefPad )
871  continue;
872 
873  // We can stop the test when pad->GetPosition().x > x_limit
874  // because the list is sorted by X values
875  if( pad->GetPosition().x > x_limit )
876  break;
877 
878  // No problem if pads which are on copper layers are on different copper layers,
879  // (pads can be only on a technical layer, to build complex pads)
880  // but their hole (if any ) can create DRC error because they are on all
881  // copper layers, so we test them
882  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
883  ( pad->GetLayerSet() & all_cu ) != 0 &&
884  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
885  {
886  // if holes are in the same location and have the same size and shape,
887  // this can be accepted
888  if( pad->GetPosition() == aRefPad->GetPosition()
889  && pad->GetDrillSize() == aRefPad->GetDrillSize()
890  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
891  {
892  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
893  continue;
894 
895  // for oval holes: must also have the same orientation
896  if( pad->GetOrientation() == aRefPad->GetOrientation() )
897  continue;
898  }
899 
900  /* Here, we must test clearance between holes and pads
901  * dummy pad size and shape is adjusted to pad drill size and shape
902  */
903  if( pad->GetDrillSize().x )
904  {
905  // pad under testing has a hole, test this hole against pad reference
906  dummypad.SetPosition( pad->GetPosition() );
907  dummypad.SetSize( pad->GetDrillSize() );
908  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
910  dummypad.SetOrientation( pad->GetOrientation() );
911 
912  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
913  {
914  // here we have a drc error on pad!
915  m_currentMarker = fillMarker( pad, aRefPad,
917  return false;
918  }
919  }
920 
921  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
922  {
923  dummypad.SetPosition( aRefPad->GetPosition() );
924  dummypad.SetSize( aRefPad->GetDrillSize() );
925  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
927  dummypad.SetOrientation( aRefPad->GetOrientation() );
928 
929  if( !checkClearancePadToPad( pad, &dummypad ) )
930  {
931  // here we have a drc error on aRefPad!
932  m_currentMarker = fillMarker( aRefPad, pad,
934  return false;
935  }
936  }
937 
938  continue;
939  }
940 
941  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
942  // But no problem if pads have the same netcode (same net)
943  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
944  continue;
945 
946  // if pads are from the same footprint
947  if( pad->GetParent() == aRefPad->GetParent() )
948  {
949  // and have the same pad number ( equivalent pads )
950 
951  // one can argue that this 2nd test is not necessary, that any
952  // two pads from a single module are acceptable. This 2nd test
953  // should eventually be a configuration option.
954  if( pad->PadNameEqual( aRefPad ) )
955  continue;
956  }
957 
958  // if either pad has no drill and is only on technical layers, not a clearance violation
959  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
960  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
961  {
962  continue;
963  }
964 
965  if( !checkClearancePadToPad( aRefPad, pad ) )
966  {
967  // here we have a drc error!
969  return false;
970  }
971  }
972 
973  return true;
974 }
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:646
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:207
MARKER_PCB * fillMarker(const 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_PAD_NEAR_PAD1
pad too close to pad
Definition: drc_stuff.h:58
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:381
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
BOARD * m_pcb
Definition: drc_stuff.h:205
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint & GetPosition() const override
Definition: class_pad.h:220
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:395
int GetNetCode() const
Function GetNetCode.
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
Function checkClearancePadToPad.
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:375
#define DRCE_HOLE_NEAR_PAD
hole too close to pad
Definition: drc_stuff.h:64
bool DRC::doTrackDrc ( TRACK aRefSeg,
TRACK aStart,
bool  doPads = true 
)
private

Function DoTrackDrc tests the current segment.

Parameters
aRefSegThe segment to test
aStartThe head of a list of tracks to test against (usually BOARD::m_Track)
doPadstrue if should do pads test
Returns
bool - true if no poblems, else false and m_currentMarker is filled in with the problem information.

Definition at line 137 of file drc_clearance_test_functions.cpp.

References abs, LSET::AllCuMask(), PNS::angle(), ArcTangente(), B_Cu, checkClearanceSegmToPad(), checkLine(), checkMarginToCircle(), delta, DRCE_ENDS_PROBLEM1, DRCE_ENDS_PROBLEM2, DRCE_ENDS_PROBLEM3, DRCE_ENDS_PROBLEM4, DRCE_ENDS_PROBLEM5, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR, 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, 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(), m_currentMarker, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, m_padToTestPos, m_pcb, 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, RotatePoint(), D_PAD::SetLayerSet(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), D_PAD::SetSize(), D_PAD::ShapePos(), EDA_ITEM::Type(), VIA_MICROVIA, wxPoint::x, and wxPoint::y.

Referenced by Drc(), DrcBlind(), and testTracks().

138 {
139  TRACK* track;
140  wxPoint delta; // length on X and Y axis of segments
141  LSET layerMask;
142  int net_code_ref;
143  wxPoint shape_pos;
144 
145  NETCLASSPTR netclass = aRefSeg->GetNetClass();
147 
148  /* In order to make some calculations more easier or faster,
149  * pads and tracks coordinates will be made relative to the reference segment origin
150  */
151  wxPoint origin = aRefSeg->GetStart(); // origin will be the origin of other coordinates
152 
153  m_segmEnd = delta = aRefSeg->GetEnd() - origin;
154  m_segmAngle = 0;
155 
156  layerMask = aRefSeg->GetLayerSet();
157  net_code_ref = aRefSeg->GetNetCode();
158 
159  // Phase 0 : Test vias
160  if( aRefSeg->Type() == PCB_VIA_T )
161  {
162  const VIA *refvia = static_cast<const VIA*>( aRefSeg );
163  // test if the via size is smaller than minimum
164  if( refvia->GetViaType() == VIA_MICROVIA )
165  {
166  if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
167  {
168  m_currentMarker = fillMarker( refvia, NULL,
170  return false;
171  }
172  if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
173  {
174  m_currentMarker = fillMarker( refvia, NULL,
176  return false;
177  }
178  }
179  else
180  {
181  if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
182  {
183  m_currentMarker = fillMarker( refvia, NULL,
185  return false;
186  }
187  if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
188  {
189  m_currentMarker = fillMarker( refvia, NULL,
191  return false;
192  }
193  }
194 
195  // test if via's hole is bigger than its diameter
196  // This test is necessary since the via hole size and width can be modified
197  // and a default via hole can be bigger than some vias sizes
198  if( refvia->GetDrillValue() > refvia->GetWidth() )
199  {
200  m_currentMarker = fillMarker( refvia, NULL,
202  return false;
203  }
204 
205  // For microvias: test if they are blind vias and only between 2 layers
206  // because they are used for very small drill size and are drill by laser
207  // and **only one layer** can be drilled
208  if( refvia->GetViaType() == VIA_MICROVIA )
209  {
210  PCB_LAYER_ID layer1, layer2;
211  bool err = true;
212 
213  refvia->LayerPair( &layer1, &layer2 );
214 
215  if( layer1 > layer2 )
216  std::swap( layer1, layer2 );
217 
218  if( layer2 == B_Cu && layer1 == m_pcb->GetDesignSettings().GetCopperLayerCount() - 2 )
219  err = false;
220  else if( layer1 == F_Cu && layer2 == In1_Cu )
221  err = false;
222 
223  if( err )
224  {
225  m_currentMarker = fillMarker( refvia, NULL,
227  return false;
228  }
229  }
230  }
231  else // This is a track segment
232  {
233  if( aRefSeg->GetWidth() < dsnSettings.m_TrackMinWidth )
234  {
235  m_currentMarker = fillMarker( aRefSeg, NULL,
237  return false;
238  }
239  }
240 
241  // for a non horizontal or vertical segment Compute the segment angle
242  // in tenths of degrees and its length
243  if( delta.x || delta.y )
244  {
245  // Compute the segment angle in 0,1 degrees
246  m_segmAngle = ArcTangente( delta.y, delta.x );
247 
248  // Compute the segment length: we build an equivalent rotated segment,
249  // this segment is horizontal, therefore dx = length
250  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
251  }
252 
253  m_segmLength = delta.x;
254 
255  /******************************************/
256  /* Phase 1 : test DRC track to pads : */
257  /******************************************/
258 
259  /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
260  * but having a hole
261  * This dummy pad has the size and shape of the hole
262  * to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
263  * Therefore, this dummy pad is a circle or an oval.
264  * A pad must have a parent because some functions expect a non null parent
265  * to find the parent board, and some other data
266  */
267  MODULE dummymodule( m_pcb ); // Creates a dummy parent
268  D_PAD dummypad( &dummymodule );
269 
270  dummypad.SetLayerSet( LSET::AllCuMask() ); // Ensure the hole is on all layers
271 
272  // Compute the min distance to pads
273  if( testPads )
274  {
275  unsigned pad_count = m_pcb->GetPadCount();
276 
277  auto pads = m_pcb->GetPads();
278 
279  for( unsigned ii = 0; ii<pad_count; ++ii )
280  {
281  D_PAD* pad = pads[ii];
282 
283  /* No problem if pads are on an other layer,
284  * But if a drill hole exists (a pad on a single layer can have a hole!)
285  * we must test the hole
286  */
287  if( !( pad->GetLayerSet() & layerMask ).any() )
288  {
289  /* We must test the pad hole. In order to use the function
290  * checkClearanceSegmToPad(),a pseudo pad is used, with a shape and a
291  * size like the hole
292  */
293  if( pad->GetDrillSize().x == 0 )
294  continue;
295 
296  dummypad.SetSize( pad->GetDrillSize() );
297  dummypad.SetPosition( pad->GetPosition() );
298  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
300  dummypad.SetOrientation( pad->GetOrientation() );
301 
302  m_padToTestPos = dummypad.GetPosition() - origin;
303 
304  if( !checkClearanceSegmToPad( &dummypad, aRefSeg->GetWidth(),
305  netclass->GetClearance() ) )
306  {
307  m_currentMarker = fillMarker( aRefSeg, pad,
309  return false;
310  }
311 
312  continue;
313  }
314 
315  // The pad must be in a net (i.e pt_pad->GetNet() != 0 )
316  // but no problem if the pad netcode is the current netcode (same net)
317  if( pad->GetNetCode() // the pad must be connected
318  && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok
319  continue;
320 
321  // DRC for the pad
322  shape_pos = pad->ShapePos();
323  m_padToTestPos = shape_pos - origin;
324 
325  if( !checkClearanceSegmToPad( pad, aRefSeg->GetWidth(), aRefSeg->GetClearance( pad ) ) )
326  {
327  m_currentMarker = fillMarker( aRefSeg, pad,
329  return false;
330  }
331  }
332  }
333 
334  /***********************************************/
335  /* Phase 2: test DRC with other track segments */
336  /***********************************************/
337 
338  // At this point the reference segment is the X axis
339 
340  // Test the reference segment with other track segments
341  wxPoint segStartPoint;
342  wxPoint segEndPoint;
343  for( track = aStart; track; track = track->Next() )
344  {
345  // No problem if segments have the same net code:
346  if( net_code_ref == track->GetNetCode() )
347  continue;
348 
349  // No problem if segment are on different layers :
350  if( !( layerMask & track->GetLayerSet() ).any() )
351  continue;
352 
353  // the minimum distance = clearance plus half the reference track
354  // width plus half the other track's width
355  int w_dist = aRefSeg->GetClearance( track );
356  w_dist += (aRefSeg->GetWidth() + track->GetWidth()) / 2;
357 
358  // Due to many double to int conversions during calculations, which
359  // create rounding issues,
360  // the exact clearance margin cannot be really known.
361  // To avoid false bad DRC detection due to these rounding issues,
362  // slightly decrease the w_dist (remove one nanometer is enough !)
363  w_dist -= 1;
364 
365  // If the reference segment is a via, we test it here
366  if( aRefSeg->Type() == PCB_VIA_T )
367  {
368  delta = track->GetEnd() - track->GetStart();
369  segStartPoint = aRefSeg->GetStart() - track->GetStart();
370 
371  if( track->Type() == PCB_VIA_T )
372  {
373  // Test distance between two vias, i.e. two circles, trivial case
374  if( EuclideanNorm( segStartPoint ) < w_dist )
375  {
376  m_currentMarker = fillMarker( aRefSeg, track,
378  return false;
379  }
380  }
381  else // test via to segment
382  {
383  // Compute l'angle du segment a tester;
384  double angle = ArcTangente( delta.y, delta.x );
385 
386  // Compute new coordinates ( the segment become horizontal)
387  RotatePoint( &delta, angle );
388  RotatePoint( &segStartPoint, angle );
389 
390  if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
391  {
392  m_currentMarker = fillMarker( track, aRefSeg,
394  return false;
395  }
396  }
397 
398  continue;
399  }
400 
401  /* We compute segStartPoint, segEndPoint = starting and ending point coordinates for
402  * the segment to test in the new axis : the new X axis is the
403  * reference segment. We must translate and rotate the segment to test
404  */
405  segStartPoint = track->GetStart() - origin;
406  segEndPoint = track->GetEnd() - origin;
407  RotatePoint( &segStartPoint, m_segmAngle );
408  RotatePoint( &segEndPoint, m_segmAngle );
409  if( track->Type() == PCB_VIA_T )
410  {
411  if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
412  continue;
413 
414  m_currentMarker = fillMarker( aRefSeg, track,
416  return false;
417  }
418 
419  /* We have changed axis:
420  * the reference segment is Horizontal.
421  * 3 cases : the segment to test can be parallel, perpendicular or have an other direction
422  */
423  if( segStartPoint.y == segEndPoint.y ) // parallel segments
424  {
425  if( abs( segStartPoint.y ) >= w_dist )
426  continue;
427 
428  // Ensure segStartPoint.x <= segEndPoint.x
429  if( segStartPoint.x > segEndPoint.x )
430  std::swap( segStartPoint.x, segEndPoint.x );
431 
432  if( segStartPoint.x > (-w_dist) && segStartPoint.x < (m_segmLength + w_dist) ) /* possible error drc */
433  {
434  // the start point is inside the reference range
435  // X........
436  // O--REF--+
437 
438  // Fine test : we consider the rounded shape of each end of the track segment:
439  if( segStartPoint.x >= 0 && segStartPoint.x <= m_segmLength )
440  {
441  m_currentMarker = fillMarker( aRefSeg, track,
443  return false;
444  }
445 
446  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
447  {
448  m_currentMarker = fillMarker( aRefSeg, track,
450  return false;
451  }
452  }
453 
454  if( segEndPoint.x > (-w_dist) && segEndPoint.x < (m_segmLength + w_dist) )
455  {
456  // the end point is inside the reference range
457  // .....X
458  // O--REF--+
459  // Fine test : we consider the rounded shape of the ends
460  if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
461  {
462  m_currentMarker = fillMarker( aRefSeg, track,
464  return false;
465  }
466 
467  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
468  {
469  m_currentMarker = fillMarker( aRefSeg, track,
471  return false;
472  }
473  }
474 
475  if( segStartPoint.x <=0 && segEndPoint.x >= 0 )
476  {
477  // the segment straddles the reference range (this actually only
478  // checks if it straddles the origin, because the other cases where already
479  // handled)
480  // X.............X
481  // O--REF--+
482  m_currentMarker = fillMarker( aRefSeg, track,
484  return false;
485  }
486  }
487  else if( segStartPoint.x == segEndPoint.x ) // perpendicular segments
488  {
489  if( ( segStartPoint.x <= (-w_dist) ) || ( segStartPoint.x >= (m_segmLength + w_dist) ) )
490  continue;
491 
492  // Test if segments are crossing
493  if( segStartPoint.y > segEndPoint.y )
494  std::swap( segStartPoint.y, segEndPoint.y );
495 
496  if( (segStartPoint.y < 0) && (segEndPoint.y > 0) )
497  {
498  m_currentMarker = fillMarker( aRefSeg, track,
500  return false;
501  }
502 
503  // At this point the drc error is due to an end near a reference segm end
504  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
505  {
506  m_currentMarker = fillMarker( aRefSeg, track,
508  return false;
509  }
510  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
511  {
512  m_currentMarker = fillMarker( aRefSeg, track,
514  return false;
515  }
516  }
517  else // segments quelconques entre eux
518  {
519  // calcul de la "surface de securite du segment de reference
520  // First rought 'and fast) test : the track segment is like a rectangle
521 
522  m_xcliplo = m_ycliplo = -w_dist;
523  m_xcliphi = m_segmLength + w_dist;
524  m_ycliphi = w_dist;
525 
526  // A fine test is needed because a serment is not exactly a
527  // rectangle, it has rounded ends
528  if( !checkLine( segStartPoint, segEndPoint ) )
529  {
530  /* 2eme passe : the track has rounded ends.
531  * we must a fine test for each rounded end and the
532  * rectangular zone
533  */
534 
535  m_xcliplo = 0;
537 
538  if( !checkLine( segStartPoint, segEndPoint ) )
539  {
540  m_currentMarker = fillMarker( aRefSeg, track,
542  return false;
543  }
544  else // The drc error is due to the starting or the ending point of the reference segment
545  {
546  // Test the starting and the ending point
547  segStartPoint = track->GetStart();
548  segEndPoint = track->GetEnd();
549  delta = segEndPoint - segStartPoint;
550 
551  // Compute the segment orientation (angle) en 0,1 degre
552  double angle = ArcTangente( delta.y, delta.x );
553 
554  // Compute the segment length: delta.x = length after rotation
555  RotatePoint( &delta, angle );
556 
557  /* Comute the reference segment coordinates relatives to a
558  * X axis = current tested segment
559  */
560  wxPoint relStartPos = aRefSeg->GetStart() - segStartPoint;
561  wxPoint relEndPos = aRefSeg->GetEnd() - segStartPoint;
562 
563  RotatePoint( &relStartPos, angle );
564  RotatePoint( &relEndPos, angle );
565 
566  if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
567  {
568  m_currentMarker = fillMarker( aRefSeg, track,
570  return false;
571  }
572 
573  if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
574  {
575  m_currentMarker = fillMarker( aRefSeg, track,
577  return false;
578  }
579  }
580  }
581  }
582  }
583 
584  return true;
585 }
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:646
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
#define DRCE_TRACK_SEGMENTS_TOO_CLOSE
2 parallel track segments too close: segm ends between segref ends
Definition: drc_stuff.h:51
MARKER_PCB * fillMarker(const 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_ycliplo
Definition: drc_stuff.h:200
#define DRCE_ENDS_PROBLEM1
track ends are too close
Definition: drc_stuff.h:53
#define DRCE_TRACK_ENDS1
2 parallel track segments too close: fine start point test
Definition: drc_stuff.h:47
#define DRCE_TOO_SMALL_MICROVIA_DRILL
Too small micro via drill.
Definition: drc_stuff.h:70
#define DRCE_TRACK_NEAR_VIA
track too close to via
Definition: drc_stuff.h:44
int m_ycliphi
Definition: drc_stuff.h:202
int m_segmLength
Definition: drc_stuff.h:194
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:381
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
const wxSize & GetDrillSize() const
Definition: class_pad.h:275
#define DRCE_TRACKS_CROSSING
tracks are crossing
Definition: drc_stuff.h:52
wxPoint m_padToTestPos
Definition: drc_stuff.h:185
#define DRCE_ENDS_PROBLEM2
track ends are too close
Definition: drc_stuff.h:54
#define abs(a)
Definition: auxiliary.h:84
#define DRCE_TOO_SMALL_MICROVIA
Too small micro via size.
Definition: drc_stuff.h:68
static const int delta[8][2]
Definition: solve.cpp:112
const wxPoint & GetEnd() const
Definition: class_track.h:120
BOARD * m_pcb
Definition: drc_stuff.h:205
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_ENDS_PROBLEM5
track ends are too close
Definition: drc_stuff.h:57
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:443
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
#define DRCE_VIA_NEAR_TRACK
via too close to track
Definition: drc_stuff.h:46
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
const wxPoint & GetStart() const
Definition: class_track.h:123
const wxPoint & GetPosition() const override
Definition: class_pad.h:220
int m_TrackMinWidth
track min value for width ((min copper size value
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:395
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...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Helper function checkMarginToCircle Check the distance from a point to a segment. ...
#define DRCE_TRACK_NEAR_PAD
pad too close to track
Definition: drc_stuff.h:43
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc_stuff.h:201
int m_MicroViasMinSize
micro vias (not vias) min diameter
unsigned GetPadCount() const
Function GetPadCount.
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
#define DRCE_TOO_SMALL_TRACK_WIDTH
Too small track width.
Definition: drc_stuff.h:66
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Function checkClearanceSegmToPad 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_stuff.h:186
TRACK * Next() const
Definition: class_track.h:100
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:117
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
#define DRCE_ENDS_PROBLEM3
track ends are too close
Definition: drc_stuff.h:55
#define DRCE_TRACK_ENDS4
2 parallel track segments too close: fine end point test
Definition: drc_stuff.h:50
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:375
#define DRCE_VIA_NEAR_VIA
via too close to via
Definition: drc_stuff.h:45
wxPoint ShapePos() const
Definition: class_pad.cpp:500
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
#define DRCE_TRACK_ENDS2
2 parallel track segments too close: fine start point test
Definition: drc_stuff.h:48
#define DRCE_TRACK_ENDS3
2 parallel track segments too close: fine end point test
Definition: drc_stuff.h:49
#define DRCE_ENDS_PROBLEM4
track ends are too close
Definition: drc_stuff.h:56
int m_xcliplo
Definition: drc_stuff.h:199
#define DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR
micro via's layer pair incorrect (layers must be adjacent)
Definition: drc_stuff.h:60
double m_segmAngle
Definition: drc_stuff.h:193
#define DRCE_TRACK_NEAR_THROUGH_HOLE
thru hole is too close to track
Definition: drc_stuff.h:42
#define DRCE_VIA_HOLE_BIGGER
via's hole is bigger than its diameter
Definition: drc_stuff.h:59
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
#define DRCE_TOO_SMALL_VIA_DRILL
Too small via drill.
Definition: drc_stuff.h:69
#define DRCE_TOO_SMALL_VIA
Too small via size.
Definition: drc_stuff.h:67
bool DRC::doTrackKeepoutDrc ( TRACK aRefSeg)
private

Function doTrackKeepoutDrc tests the current segment or via.

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

Definition at line 794 of file drc.cpp.

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

Referenced by Drc(), and DrcBlind().

795 {
796  // Test keepout areas for vias, tracks and pads inside keepout areas
797  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
798  {
799  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
800 
801  if( !area->GetIsKeepout() )
802  continue;
803 
804  if( aRefSeg->Type() == PCB_TRACE_T )
805  {
806  if( ! area->GetDoNotAllowTracks() )
807  continue;
808 
809  if( !area->IsOnLayer( aRefSeg->GetLayer() ) )
810  continue;
811 
812  if( area->Outline()->Distance( SEG( aRefSeg->GetStart(), aRefSeg->GetEnd() ),
813  aRefSeg->GetWidth() ) == 0 )
814  {
815  m_currentMarker = fillMarker( aRefSeg, NULL,
817  return false;
818  }
819  }
820  else if( aRefSeg->Type() == PCB_VIA_T )
821  {
822  if( ! area->GetDoNotAllowVias() )
823  continue;
824 
825  auto viaLayers = aRefSeg->GetLayerSet();
826 
827  if( !area->CommonLayerExists( viaLayers ) )
828  continue;
829 
830  if( area->Outline()->Distance( aRefSeg->GetPosition() ) < aRefSeg->GetWidth()/2 )
831  {
832  m_currentMarker = fillMarker( aRefSeg, NULL,
834  return false;
835  }
836  }
837  }
838 
839  return true;
840 }
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
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:201
MARKER_PCB * fillMarker(const 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...
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:272
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:262
const wxPoint & GetEnd() const
Definition: class_track.h:120
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc_stuff.h:78
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc_stuff.h:205
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:672
const wxPoint & GetPosition() const override
Definition: class_track.h:114
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc_stuff.h:77
const wxPoint & GetStart() const
Definition: class_track.h:123
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:675
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
bool GetDoNotAllowVias() const
Definition: class_zone.h:674
int GetWidth() const
Definition: class_track.h:117
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
int DRC::Drc ( TRACK aRefSeg,
TRACK aList 
)

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

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

Definition at line 155 of file drc.cpp.

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

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

156 {
157  updatePointers();
158 
159  if( !doTrackDrc( aRefSegm, aList, true ) )
160  {
161  wxASSERT( m_currentMarker );
162 
164  return BAD_DRC;
165  }
166 
167  if( !doTrackKeepoutDrc( aRefSegm ) )
168  {
169  wxASSERT( m_currentMarker );
170 
172  return BAD_DRC;
173  }
174 
175  return OK_DRC;
176 }
#define OK_DRC
Definition: drc_stuff.h:35
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Function doTrackKeepoutDrc tests the current segment or via.
Definition: drc.cpp:794
#define BAD_DRC
Definition: drc_stuff.h:36
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:784
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Function DoTrackDrc tests the current segment.
int DRC::Drc ( ZONE_CONTAINER aArea,
int  aCornerIndex 
)

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

Test Edge inside other areas Test Edge too close other areas

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

Definition at line 179 of file drc.cpp.

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

180 {
181  updatePointers();
182 
183  if( !doEdgeZoneDrc( aArea, aCornerIndex ) )
184  {
185  wxASSERT( m_currentMarker );
187  return BAD_DRC;
188  }
189 
190  return OK_DRC;
191 }
#define OK_DRC
Definition: drc_stuff.h:35
#define BAD_DRC
Definition: drc_stuff.h:36
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:784
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
bool doEdgeZoneDrc(ZONE_CONTAINER *aArea, int aCornerIndex)
Function doEdgeZoneDrc tests a segment in ZONE_CONTAINER * aArea: Test Edge inside other areas Test E...
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
int DRC::DrcBlind ( TRACK aRefSeg,
TRACK aList 
)
inline

Function DrcBlind tests the current segment and returns the result.

Any error is not displayed in the status panel.

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

Definition at line 451 of file drc_stuff.h.

References BAD_DRC, doTrackDrc(), doTrackKeepoutDrc(), OK_DRC, and updatePointers().

452  {
453  updatePointers();
454 
455  if( ! doTrackDrc( aRefSeg, aList ) )
456  return BAD_DRC;
457 
458  return doTrackKeepoutDrc( aRefSeg ) ? OK_DRC : BAD_DRC;
459  }
#define OK_DRC
Definition: drc_stuff.h:35
bool doTrackKeepoutDrc(TRACK *aRefSeg)
Function doTrackKeepoutDrc tests the current segment or via.
Definition: drc.cpp:794
#define BAD_DRC
Definition: drc_stuff.h:36
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Function DoTrackDrc tests the current segment.
MARKER_PCB * DRC::fillMarker ( const 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
aTrackThe reference track.
aItemAnother item on the BOARD, such as a VIA, SEGZONE, or TRACK.
aErrorCodeA categorizing identifier for the particular type of error that is being reported.
fillMeA MARKER_PCB* which is to be filled in, or NULL if one is to first be allocated, then filled.

Definition at line 49 of file drc_marker_functions.cpp.

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

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

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

Definition at line 128 of file drc_marker_functions.cpp.

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

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

Definition at line 170 of file drc_marker_functions.cpp.

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

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

Definition at line 228 of file drc_marker_functions.cpp.

References MARKER_BASE::SetData().

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

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
aAreaThe zone to test
aPosposition of error
aErrorCodeType of error
fillMeA MARKER_PCB* which is to be filled in, or NULL if one is to first be allocated, then filled.

Definition at line 190 of file drc_marker_functions.cpp.

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

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

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

Definition at line 213 of file drc_marker_functions.cpp.

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

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

Definition at line 534 of file drc_stuff.h.

References m_currentMarker.

Referenced by PCB_EDIT_FRAME::Other_Layer_Route().

535  {
536  return m_currentMarker;
537  }
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
void DRC::ListUnconnectedPads ( )

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

Definition at line 315 of file drc.cpp.

References testUnconnected(), and updatePointers().

Referenced by DIALOG_DRC_CONTROL::OnListUnconnectedClick().

316 {
317  testUnconnected();
318 
319  // update the m_drcDialog listboxes
320  updatePointers();
321 }
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
void testUnconnected()
Definition: drc.cpp:548
void DRC::RunTests ( wxTextCtrl *  aMessages = NULL)

Function RunTests will actually 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 194 of file drc.cpp.

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

Referenced by DIALOG_DRC_CONTROL::OnStartdrcClick().

195 {
196  // be sure m_pcb is the current board, not a old one
197  // ( the board can be reloaded )
199 
200  // someone should have cleared the two lists before calling this.
201 
202  if( !testNetClasses() )
203  {
204  // testing the netclasses is a special case because if the netclasses
205  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
206  // class (a NET) will cause its items such as tracks, vias, and pads
207  // to also fail. So quit after *all* netclass errors have been reported.
208  if( aMessages )
209  aMessages->AppendText( _( "Aborting\n" ) );
210 
211  // update the m_drcDialog listboxes
212  updatePointers();
213 
214  return;
215  }
216 
217  // test pad to pad clearances, nothing to do with tracks, vias or zones.
218  if( m_doPad2PadTest )
219  {
220  if( aMessages )
221  {
222  aMessages->AppendText( _( "Pad clearances...\n" ) );
223  wxSafeYield();
224  }
225 
226  testPad2Pad();
227  }
228 
229  // test track and via clearances to other tracks, pads, and vias
230  if( aMessages )
231  {
232  aMessages->AppendText( _( "Track clearances...\n" ) );
233  wxSafeYield();
234  }
235 
236  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
237 
238  // Before testing segments and unconnected, refill all zones:
239  // this is a good caution, because filled areas can be outdated.
240  if( aMessages )
241  {
242  aMessages->AppendText( _( "Fill zones...\n" ) );
243  wxSafeYield();
244  }
245 
246  m_pcbEditorFrame->Fill_All_Zones( aMessages ? aMessages->GetParent() : m_pcbEditorFrame,
247  false );
248 
249  // test zone clearances to other zones
250  if( aMessages )
251  {
252  aMessages->AppendText( _( "Test zones...\n" ) );
253  wxSafeYield();
254  }
255 
256  testZones();
257 
258  // find and gather unconnected pads.
259  if( m_doUnconnectedTest )
260  {
261  if( aMessages )
262  {
263  aMessages->AppendText( _( "Unconnected pads...\n" ) );
264  aMessages->Refresh();
265  }
266 
267  testUnconnected();
268  }
269 
270  // find and gather vias, tracks, pads inside keepout areas.
271  if( m_doKeepoutTest )
272  {
273  if( aMessages )
274  {
275  aMessages->AppendText( _( "Keepout areas ...\n" ) );
276  aMessages->Refresh();
277  }
278 
280  }
281 
282  // find and gather vias, tracks, pads inside text boxes.
283  if( aMessages )
284  {
285  aMessages->AppendText( _( "Test texts...\n" ) );
286  wxSafeYield();
287  }
288 
289  testTexts();
290 
291  // find overlaping courtyard ares.
293  {
294  if( aMessages )
295  {
296  aMessages->AppendText( _( "Courtyard areas...\n" ) );
297  aMessages->Refresh();
298  }
299 
301  }
302 
303  // update the m_drcDialog listboxes
304  updatePointers();
305 
306  if( aMessages )
307  {
308  // no newline on this one because it is last, don't want the window
309  // to unnecessarily scroll.
310  aMessages->AppendText( _( "Finished" ) );
311  }
312 }
bool m_doNoCourtyardDefined
Definition: drc_stuff.h:172
int Fill_All_Zones(wxWindow *aActiveWindow, bool aVerbose=true)
Function Fill_All_Zones Fill all zones on the board The old fillings are removed. ...
void testKeepoutAreas()
Definition: drc.cpp:616
BOARD * GetBoard() const
void testTexts()
Definition: drc.cpp:670
BOARD * m_pcb
Definition: drc_stuff.h:205
bool m_doFootprintOverlapping
Definition: drc_stuff.h:171
bool m_doKeepoutTest
Definition: drc_stuff.h:169
void testZones()
Definition: drc.cpp:578
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
bool m_doPad2PadTest
Definition: drc_stuff.h:166
void testPad2Pad()
Definition: drc.cpp:454
bool doFootprintOverlappingDrc()
Function doFootprintOverlappingDrc tests for footprint courtyard overlaps.
Definition: drc.cpp:977
bool testNetClasses()
Function testNetClasses goes through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings.
Definition: drc.cpp:431
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Function testTracks performs the DRC on all tracks.
Definition: drc.cpp:493
void testUnconnected()
Definition: drc.cpp:548
bool m_doUnconnectedTest
Definition: drc_stuff.h:167
void DRC::SetSettings ( bool  aPad2PadTest,
bool  aUnconnectedTest,
bool  aZonesTest,
bool  aKeepoutTest,
bool  aCourtyardTest,
bool  aCourtyardMissingTest,
const wxString &  aReportName,
bool  aSaveReport 
)
inline

Function SetSettings saves 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.
aKeepoutTestTells whether to test keepout areas.
aCourtyardTestTells whether to test footprint courtyard overlap.
aCourtyardMissingTestTells whether to test missing courtyard definition in footprint.
aReportNameA string telling the disk file report name entered.
aSaveReportA boolean telling whether to generate disk file report.

Definition at line 500 of file drc_stuff.h.

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

504  {
505  m_doPad2PadTest = aPad2PadTest;
506  m_doUnconnectedTest = aUnconnectedTest;
507  m_doZonesTest = aZonesTest;
508  m_doKeepoutTest = aKeepoutTest;
509  m_rptFilename = aReportName;
510  m_doCreateRptFile = aSaveReport;
511  m_doFootprintOverlapping = aCourtyardTest;
512  m_doNoCourtyardDefined = aCourtyardMissingTest;
513  }
bool m_doNoCourtyardDefined
Definition: drc_stuff.h:172
bool m_doCreateRptFile
Definition: drc_stuff.h:170
bool m_doFootprintOverlapping
Definition: drc_stuff.h:171
bool m_doKeepoutTest
Definition: drc_stuff.h:169
bool m_doZonesTest
Definition: drc_stuff.h:168
bool m_doPad2PadTest
Definition: drc_stuff.h:166
wxString m_rptFilename
Definition: drc_stuff.h:174
bool m_doUnconnectedTest
Definition: drc_stuff.h:167
void DRC::ShowDRCDialog ( wxWindow *  aParent = NULL)

Function ShowDRCDialog opens 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 an other 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 an other dialog, not from the PCB editor frame

Definition at line 58 of file drc.cpp.

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

59 {
60  bool show_dlg_modal = true;
61 
62  // the dialog needs a parent frame. if it is not specified, this is
63  // the PCB editor frame specified in DRC class.
64  if( aParent == NULL )
65  {
66  // if any parent is specified, the dialog is modal.
67  // if this is the default PCB editor frame, it is not modal
68  show_dlg_modal = false;
69  aParent = m_pcbEditorFrame;
70  }
71 
72  if( !m_drcDialog )
73  {
75  m_drcDialog = new DIALOG_DRC_CONTROL( this, m_pcbEditorFrame, aParent );
77 
79 
80  if( show_dlg_modal )
81  m_drcDialog->ShowModal();
82  else
83  m_drcDialog->Show( true );
84  }
85  else // The dialog is just not visible (because the user has double clicked on an error item)
86  {
88  m_drcDialog->Show( true );
89  }
90 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:53
bool m_doCreateRptFile
Definition: drc_stuff.h:170
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc_stuff.h:206
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:125
void updatePointers()
Function updatePointers is a private helper function used to update needed pointers from the one poin...
Definition: drc.cpp:324
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
bool Show(bool show) override
friend class DIALOG_DRC_CONTROL
Definition: drc_stuff.h:160
TOOL_MANAGER * GetToolManager() const
Function GetToolManager returns the tool manager instance, if any.
Definition: draw_frame.h:877
wxString m_rptFilename
Definition: drc_stuff.h:174
void SetRptSettings(bool aEnable, const wxString &aFileName)
Enable/disable the report file creation.
Definition: dialog_drc.cpp:156
void DRC::testKeepoutAreas ( )
private

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

617 {
618  // Test keepout areas for vias, tracks and pads inside keepout areas
619  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
620  {
621  ZONE_CONTAINER* area = m_pcb->GetArea( ii );
622 
623  if( !area->GetIsKeepout() )
624  {
625  continue;
626  }
627 
628  for( TRACK* segm = m_pcb->m_Track; segm != NULL; segm = segm->Next() )
629  {
630  if( segm->Type() == PCB_TRACE_T )
631  {
632  if( ! area->GetDoNotAllowTracks() )
633  continue;
634 
635  // Ignore if the keepout zone is not on the same layer
636  if( !area->IsOnLayer( segm->GetLayer() ) )
637  continue;
638 
639  if( area->Outline()->Distance( SEG( segm->GetStart(), segm->GetEnd() ),
640  segm->GetWidth() ) == 0 )
641  {
642  addMarkerToPcb( fillMarker( segm, NULL,
644  m_currentMarker = nullptr;
645  }
646  }
647  else if( segm->Type() == PCB_VIA_T )
648  {
649  if( ! area->GetDoNotAllowVias() )
650  continue;
651 
652  auto viaLayers = segm->GetLayerSet();
653 
654  if( !area->CommonLayerExists( viaLayers ) )
655  continue;
656 
657  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
658  {
659  addMarkerToPcb( fillMarker( segm, NULL,
661  m_currentMarker = nullptr;
662  }
663  }
664  }
665  // Test pads: TODO
666  }
667 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
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:201
MARKER_PCB * fillMarker(const 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...
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:272
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:262
#define DRCE_TRACK_INSIDE_KEEPOUT
Track in inside a keepout area.
Definition: drc_stuff.h:78
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
BOARD * m_pcb
Definition: drc_stuff.h:205
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:672
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
#define DRCE_VIA_INSIDE_KEEPOUT
Via in inside a keepout area.
Definition: drc_stuff.h:77
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
Definition: seg.h:36
bool GetDoNotAllowTracks() const
Definition: class_zone.h:675
TRACK * Next() const
Definition: class_track.h:100
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
bool GetDoNotAllowVias() const
Definition: class_zone.h:674
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
bool DRC::testNetClasses ( )
private

Function testNetClasses goes 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 431 of file drc.cpp.

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

Referenced by RunTests().

432 {
433  bool ret = true;
434 
436 
437  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
438 
439  if( !doNetClass( netclasses.GetDefault(), msg ) )
440  ret = false;
441 
442  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
443  {
444  NETCLASSPTR nc = i->second;
445 
446  if( !doNetClass( nc, msg ) )
447  ret = false;
448  }
449 
450  return ret;
451 }
iterator end()
NETCLASS_MAP::const_iterator const_iterator
BOARD * m_pcb
Definition: drc_stuff.h:205
iterator begin()
Class NETCLASSES is a container for NETCLASS instances.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
NETCLASSPTR GetDefault() const
Function GetDefault.
bool doNetClass(std::shared_ptr< NETCLASS > aNetClass, wxString &msg)
Definition: drc.cpp:339
NETCLASSES m_NetClasses
List of current netclasses. There is always the default netclass.
void DRC::testPad2Pad ( )
private

Definition at line 454 of file drc.cpp.

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

Referenced by RunTests().

455 {
456  std::vector<D_PAD*> sortedPads;
457 
458  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
459 
460  // find the max size of the pads (used to stop the test)
461  int max_size = 0;
462 
463  for( unsigned i = 0; i < sortedPads.size(); ++i )
464  {
465  D_PAD* pad = sortedPads[i];
466 
467  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
468  int radius = pad->GetBoundingRadius();
469  if( radius > max_size )
470  max_size = radius;
471  }
472 
473  // Test the pads
474  D_PAD** listEnd = &sortedPads[ sortedPads.size() ];
475 
476  for( unsigned i = 0; i< sortedPads.size(); ++i )
477  {
478  D_PAD* pad = sortedPads[i];
479 
480  int x_limit = max_size + pad->GetClearance() +
481  pad->GetBoundingRadius() + pad->GetPosition().x;
482 
483  if( !doPadToPadsDrc( pad, &sortedPads[i], listEnd, x_limit ) )
484  {
485  wxASSERT( m_currentMarker );
487  m_currentMarker = nullptr;
488  }
489  }
490 }
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_stuff.h:205
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:586
const wxPoint & GetPosition() const override
Definition: class_pad.h:220
bool doPadToPadsDrc(D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Function doPadToPadsDrc tests the clearance between aRefPad and other pads.
Definition: drc.cpp:843
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:546
void DRC::testTexts ( )
private

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

671 {
672  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
673  std::vector<D_PAD*> padList = m_pcb->GetPads();
674 
675  // Test text areas for vias, tracks and pads inside text areas
676  for( auto item : m_pcb->Drawings() )
677  {
678  // Drc test only items on copper layers
679  if( ! IsCopperLayer( item->GetLayer() ) )
680  continue;
681 
682  // only texts on copper layers are tested
683  if( item->Type() != PCB_TEXT_T )
684  continue;
685 
686  textShape.clear();
687 
688  // So far the bounding box makes up the text-area
689  TEXTE_PCB* text = (TEXTE_PCB*) item;
690  text->TransformTextShapeToSegmentList( textShape );
691 
692  if( textShape.size() == 0 ) // Should not happen (empty text?)
693  continue;
694 
695  for( TRACK* track = m_pcb->m_Track; track != NULL; track = track->Next() )
696  {
697  if( ! track->IsOnLayer( item->GetLayer() ) )
698  continue;
699 
700  // Test the distance between each segment and the current track/via
701  int min_dist = ( track->GetWidth() + text->GetThickness() ) /2 +
702  track->GetClearance(NULL);
703 
704  if( track->Type() == PCB_TRACE_T )
705  {
706  SEG segref( track->GetStart(), track->GetEnd() );
707 
708  // Error condition: Distance between text segment and track segment is
709  // smaller than the clearance of the segment
710  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
711  {
712  SEG segtest( textShape[jj], textShape[jj+1] );
713  int dist = segref.Distance( segtest );
714 
715  if( dist < min_dist )
716  {
717  addMarkerToPcb( fillMarker( track, text,
719  m_currentMarker ) );
720  m_currentMarker = nullptr;
721  break;
722  }
723  }
724  }
725  else if( track->Type() == PCB_VIA_T )
726  {
727  // Error condition: Distance between text segment and via is
728  // smaller than the clearance of the via
729  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
730  {
731  SEG segtest( textShape[jj], textShape[jj+1] );
732 
733  if( segtest.PointCloserThan( track->GetPosition(), min_dist ) )
734  {
735  addMarkerToPcb( fillMarker( track, text,
737  m_currentMarker = nullptr;
738  break;
739  }
740  }
741  }
742  }
743 
744  // Test pads
745  for( unsigned ii = 0; ii < padList.size(); ii++ )
746  {
747  D_PAD* pad = padList[ii];
748 
749  if( ! pad->IsOnLayer( item->GetLayer() ) )
750  continue;
751 
752  wxPoint shape_pos = pad->ShapePos();
753 
754  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
755  {
756  /* In order to make some calculations more easier or faster,
757  * pads and tracks coordinates will be made relative
758  * to the segment origin
759  */
760  wxPoint origin = textShape[jj]; // origin will be the origin of other coordinates
761  m_segmEnd = textShape[jj+1] - origin;
763  m_segmAngle = 0;
764 
765  // for a non horizontal or vertical segment Compute the segment angle
766  // in tenths of degrees and its length
767  if( delta.x || delta.y ) // delta.x == delta.y == 0 for vias
768  {
769  // Compute the segment angle in 0,1 degrees
770  m_segmAngle = ArcTangente( delta.y, delta.x );
771 
772  // Compute the segment length: we build an equivalent rotated segment,
773  // this segment is horizontal, therefore dx = length
774  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
775  }
776 
777  m_segmLength = delta.x;
778  m_padToTestPos = shape_pos - origin;
779 
780  if( !checkClearanceSegmToPad( pad, text->GetThickness(),
781  pad->GetClearance(NULL) ) )
782  {
783  addMarkerToPcb( fillMarker( pad, text,
785  m_currentMarker = nullptr;
786  break;
787  }
788  }
789  }
790  }
791 }
MARKER_PCB * fillMarker(const 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...
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_stuff.h:194
#define DRCE_VIA_INSIDE_TEXT
Via in inside a text area.
Definition: drc_stuff.h:80
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
#define DRCE_PAD_INSIDE_TEXT
Pad in inside a text area.
Definition: drc_stuff.h:82
wxPoint m_padToTestPos
Definition: drc_stuff.h:185
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:154
BOARD * m_pcb
Definition: drc_stuff.h:205
#define DRCE_TRACK_INSIDE_TEXT
Track in inside a text area.
Definition: drc_stuff.h:81
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:271
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
Definition: seg.h:36
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Function checkClearanceSegmToPad 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_stuff.h:186
TRACK * Next() const
Definition: class_track.h:100
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:493
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:546
wxPoint ShapePos() const
Definition: class_pad.cpp:500
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:246
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Function IsOnLayer tests to see if this object is on the given layer.
Definition: class_pad.h:637
double m_segmAngle
Definition: drc_stuff.h:193
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
void DRC::testTracks ( wxWindow *  aActiveWindow,
bool  aShowProgressBar 
)
private

Function testTracks performs the DRC on all tracks.

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

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

Referenced by RunTests().

494 {
495  wxProgressDialog * progressDialog = NULL;
496  const int delta = 500; // This is the number of tests between 2 calls to the
497  // progress bar
498  int count = 0;
499  for( TRACK* segm = m_pcb->m_Track; segm && segm->Next(); segm = segm->Next() )
500  count++;
501 
502  int deltamax = count/delta;
503 
504  if( aShowProgressBar && deltamax > 3 )
505  {
506  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
507  deltamax, aActiveWindow,
508  wxPD_AUTO_HIDE | wxPD_CAN_ABORT |
509  wxPD_APP_MODAL | wxPD_ELAPSED_TIME );
510  progressDialog->Update( 0, wxEmptyString );
511  }
512 
513  int ii = 0;
514  count = 0;
515 
516  for( TRACK* segm = m_pcb->m_Track; segm; segm = segm->Next() )
517  {
518  if ( ii++ > delta )
519  {
520  ii = 0;
521  count++;
522 
523  if( progressDialog )
524  {
525  if( !progressDialog->Update( count, wxEmptyString ) )
526  break; // Aborted by user
527 #ifdef __WXMAC__
528  // Work around a dialog z-order issue on OS X
529  if( count == deltamax )
530  aActiveWindow->Raise();
531 #endif
532  }
533  }
534 
535  if( !doTrackDrc( segm, segm->Next(), true ) )
536  {
537  wxASSERT( m_currentMarker );
539  m_currentMarker = nullptr;
540  }
541  }
542 
543  if( progressDialog )
544  progressDialog->Destroy();
545 }
static const int delta[8][2]
Definition: solve.cpp:112
BOARD * m_pcb
Definition: drc_stuff.h:205
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
TRACK * Next() const
Definition: class_track.h:100
bool doTrackDrc(TRACK *aRefSeg, TRACK *aStart, bool doPads=true)
Function DoTrackDrc tests the current segment.
DLIST< TRACK > m_Track
Definition: class_board.h:246
void DRC::testUnconnected ( )
private

Definition at line 548 of file drc.cpp.

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

Referenced by ListUnconnectedPads(), and RunTests().

549 {
550 
551  auto connectivity = m_pcb->GetConnectivity();
552 
553  connectivity->Clear();
554  connectivity->Build(m_pcb); // just in case. This really needs to be reliable.
555  connectivity->RecalculateRatsnest();
556 
557  std::vector<CN_EDGE> edges;
558  connectivity->GetUnconnectedEdges( edges );
559 
560  for( const auto& edge : edges )
561  {
562  wxString t_src = edge.GetSourceNode()->Parent()->GetSelectMenuText();
563  wxString t_dst = edge.GetTargetNode()->Parent()->GetSelectMenuText();
564  auto src = edge.GetSourcePos();
565  auto dst = edge.GetTargetPos();
566 
567 
568  DRC_ITEM* uncItem = new DRC_ITEM( DRCE_UNCONNECTED_ITEMS,
569  t_src,
570  t_dst,
571  wxPoint( src.x, src.y ), wxPoint( dst.x, dst.y ) );
572  m_unconnected.push_back( uncItem );
573 
574  }
575 }
Class DRC_ITEM is a holder for a DRC (in Pcbnew) or ERC (in Eeschema) error item. ...
#define DRCE_UNCONNECTED_ITEMS
items are unconnected
Definition: drc_stuff.h:41
BOARD * m_pcb
Definition: drc_stuff.h:205
DRC_LIST m_unconnected
list of unconnected pads, as DRC_ITEMs
Definition: drc_stuff.h:208
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
void DRC::testZones ( )
private

Definition at line 578 of file drc.cpp.

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

Referenced by RunTests().

579 {
580  // Test copper areas for valid netcodes
581  // if a netcode is < 0 the netname was not found when reading a netlist
582  // if a netcode is == 0 the netname is void, and the zone is not connected.
583  // This is allowed, but i am not sure this is a good idea
584  //
585  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
586  // is stored, and initalized from the file or the zone properpies editor.
587  // if it differs from the net name from net code, there is a DRC issue
588  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
589  {
590  ZONE_CONTAINER* test_area = m_pcb->GetArea( ii );
591 
592  if( !test_area->IsOnCopperLayer() )
593  continue;
594 
595  int netcode = test_area->GetNetCode();
596 
597  // a netcode < 0 or > 0 and no pad in net is a error or strange
598  // perhaps a "dead" net, which happens when all pads in this net were removed
599  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
600  int pads_in_net = (test_area->GetNetCode() > 0) ?
601  m_pcb->GetConnectivity()->GetPadCount( test_area->GetNetCode() ) : 1;
602 
603  if( ( netcode < 0 ) || pads_in_net == 0 )
604  {
605  addMarkerToPcb( fillMarker( test_area,
607  m_currentMarker = nullptr;
608  }
609  }
610 
611  // Test copper areas outlines, and create markers when needed
613 }
#define DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE
copper area has a net but no pads in nets, which is suspicious
Definition: drc_stuff.h:63
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
MARKER_PCB * fillMarker(const 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...
BOARD * m_pcb
Definition: drc_stuff.h:205
void addMarkerToPcb(MARKER_PCB *aMarker)
Function addMarkerToPcb Adds a DRC marker to the PCB throught the COMMIT mechanism.
Definition: drc.cpp:92
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
int GetNetCode() const
Function GetNetCode.
MARKER_PCB * m_currentMarker
Definition: drc_stuff.h:176
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:188
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
int Test_Drc_Areas_Outlines_To_Areas_Outlines(ZONE_CONTAINER *aArea_To_Examine, bool aCreate_Markers)
Function Test_Drc_Areas_Outlines_To_Areas_Outlines tests area outlines for DRC: Tests areas inside ot...
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
void DRC::updatePointers ( )
private

Function updatePointers is a private helper function used to update needed pointers from the one pointer which is known not to change, m_pcbEditorFrame.

Definition at line 324 of file drc.cpp.

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

Referenced by Drc(), DrcBlind(), ListUnconnectedPads(), RunTests(), and ShowDRCDialog().

325 {
326  // update my pointers, m_pcbEditorFrame is the only unchangeable one
328 
329  if( m_drcDialog ) // Use diag list boxes only in DRC dialog
330  {
333 
335  }
336 }
DIALOG_DRC_CONTROL * m_drcDialog
Definition: drc_stuff.h:206
void UpdateDisplayedCounts()
Definition: dialog_drc.cpp:690
void SetList(DRC_ITEM_LIST *aList)
Function SetList sets the DRC_ITEM_LIST for this listbox.
BOARD * GetBoard() const
DRCLISTBOX * m_UnconnectedListBox
BOARD * m_pcb
Definition: drc_stuff.h:205
DRCLISTBOX * m_ClearanceListBox
Class DRC_LIST_MARKERS is an implementation of the interface named DRC_ITEM_LIST which uses a BOARD i...
PCB_EDIT_FRAME * m_pcbEditorFrame
The pcb frame editor which owns the board.
Definition: drc_stuff.h:204
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_stuff.h:208

Friends And Related Function Documentation

friend class DIALOG_DRC_CONTROL
friend

Definition at line 160 of file drc_stuff.h.

Referenced by ShowDRCDialog().

Member Data Documentation

bool DRC::m_abortDRC
private

Definition at line 178 of file drc_stuff.h.

Referenced by DRC().

bool DRC::m_doCreateRptFile
private

Definition at line 170 of file drc_stuff.h.

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

bool DRC::m_doFootprintOverlapping
private

Definition at line 171 of file drc_stuff.h.

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

bool DRC::m_doKeepoutTest
private

Definition at line 169 of file drc_stuff.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doNoCourtyardDefined
private

Definition at line 172 of file drc_stuff.h.

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

bool DRC::m_doPad2PadTest
private

Definition at line 166 of file drc_stuff.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doUnconnectedTest
private

Definition at line 167 of file drc_stuff.h.

Referenced by DRC(), and RunTests().

bool DRC::m_doZonesTest
private

Definition at line 168 of file drc_stuff.h.

Referenced by DRC().

DIALOG_DRC_CONTROL* DRC::m_drcDialog
private

Definition at line 206 of file drc_stuff.h.

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

bool DRC::m_drcInProgress
private

Definition at line 179 of file drc_stuff.h.

Referenced by DRC().

wxPoint DRC::m_padToTestPos
private
PCB_EDIT_FRAME* DRC::m_pcbEditorFrame
private

The pcb frame editor which owns the board.

Definition at line 204 of file drc_stuff.h.

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

wxString DRC::m_rptFilename
private

Definition at line 174 of file drc_stuff.h.

Referenced by DestroyDRCDialog(), and ShowDRCDialog().

double DRC::m_segmAngle
private
wxPoint DRC::m_segmEnd
private
int DRC::m_segmLength
private
DRC_LIST DRC::m_unconnected
private

list of unconnected pads, as DRC_ITEMs

Definition at line 208 of file drc_stuff.h.

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

int DRC::m_xcliphi
private

Definition at line 201 of file drc_stuff.h.

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

int DRC::m_xcliplo
private

Definition at line 199 of file drc_stuff.h.

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

int DRC::m_ycliphi
private

Definition at line 202 of file drc_stuff.h.

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

int DRC::m_ycliplo
private

Definition at line 200 of file drc_stuff.h.

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


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