KiCad PCB EDA Suite
DRC Class Reference

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

#include <drc.h>

Inheritance diagram for DRC:
PCB_TOOL_BASE TOOL_INTERACTIVE TOOL_BASE

Public Types

enum  RESET_REASON { RUN, MODEL_RELOAD, GAL_SWITCH }
 

Determines the reason of reset for a tool

More...
 

Public Member Functions

 DRC ()
 
 ~DRC ()
 
void Reset (RESET_REASON aReason) override
 Function Reset() Brings the tool to a known, initial state. More...
 
int TestZoneToZoneOutlines ()
 Tests whether distance between zones complies with the DRC rules. More...
 
void ShowDRCDialog (wxWindow *aParent)
 Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and creates the MARKERS. More...
 
int ShowDRCDialog (const TOOL_EVENT &aEvent)
 
bool IsDRCDialogShown ()
 Check to see if the DRC dialog is currently shown. More...
 
void DestroyDRCDialog (int aReason)
 Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence. More...
 
void RunTests (wxTextCtrl *aMessages=NULL)
 Run all the tests specified with a previous call to SetSettings() More...
 
virtual bool Init () override
 Function Init() Init() is called once upon a registration of the tool. More...
 
void SetEditModules (bool aEnabled)
 Function SetEditModules() More...
 
bool EditingModules () const
 
void Activate ()
 Function Activate() Runs the tool. More...
 
TOOL_MENUGetToolMenu ()
 
void SetContextMenu (ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger=CMENU_BUTTON)
 Function SetContextMenu() More...
 
void RunMainStack (std::function< void()> aFunc)
 Function RunMainStack() More...
 
template<class T >
void Go (int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
 Function Go() More...
 
TOOL_EVENTWait (const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
 Function Wait() More...
 
TOOL_TYPE GetType () const
 Function GetType() Returns the type of the tool. More...
 
TOOL_ID GetId () const
 Function GetId() Returns the unique identifier of the tool. More...
 
const std::string & GetName () const
 Function GetName() Returns the name of the tool. More...
 
TOOL_MANAGERGetManager () const
 Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool. More...
 
bool IsToolActive () const
 

Static Public Member Functions

static void TestFootprints (NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS aUnits, std::vector< DRC_ITEM * > &aDRCList)
 Test the board footprints against a netlist. More...
 

Protected Types

enum  INTERACTIVE_PLACEMENT_OPTIONS { IPO_ROTATE = 1, IPO_FLIP = 2, IPO_SINGLE_CLICK = 4, IPO_REPEAT = 8 }
 

Protected Member Functions

void doInteractiveItemPlacement (const std::string &aTool, INTERACTIVE_PLACER_BASE *aPlacer, const wxString &aCommitMessage, int aOptions=IPO_ROTATE|IPO_FLIP|IPO_REPEAT)
 Helper function for performing a common interactive idiom: wait for a left click, place an item there (perhaps with a dialog or other user interaction), then have it move with the mouse and respond to rotate/flip, etc. More...
 
KIGFX::PCB_VIEWview () const
 
KIGFX::VIEW_CONTROLScontrols () const
 
PCB_BASE_EDIT_FRAMEframe () const
 
BOARDboard () const
 
MODULEmodule () const
 
const PCB_DISPLAY_OPTIONSdisplayOptions () const
 
PCB_DRAW_PANEL_GALcanvas () const
 
const PCBNEW_SELECTIONselection () const
 
PCBNEW_SELECTIONselection ()
 
void attachManager (TOOL_MANAGER *aManager)
 Function attachManager() More...
 
KIGFX::VIEWgetView () const
 Function getView() More...
 
KIGFX::VIEW_CONTROLSgetViewControls () const
 Function getViewControls() More...
 
template<typename T >
T * getEditFrame () const
 Function getEditFrame() More...
 
template<typename T >
T * getModel () const
 Function getModel() More...
 

Protected Attributes

bool m_editModules
 
TOOL_MENU m_menu
 functions below are not yet implemented - their interface may change More...
 
TOOL_TYPE m_type
 

Stores the type of the tool.

More...
 
TOOL_ID m_toolId
 

Unique identifier for the tool, assigned by a TOOL_MANAGER instance.

More...
 
std::string m_toolName
 

Name of the tool.

More...
 
TOOL_MANAGERm_toolMgr
 

Private Member Functions

void setTransitions () override
 

Sets up handlers for various events.

More...
 
void updatePointers ()
 Update needed pointers from the one pointer which is known not to change. More...
 
EDA_UNITS userUnits () const
 
void addMarkerToPcb (MARKER_PCB *aMarker)
 Adds a DRC marker to the PCB through the COMMIT mechanism. More...
 
wxPoint getLocation (TRACK *aTrack, ZONE_CONTAINER *aConflictZone) const
 Fetches a reasonable point for marking a violoation between two non-point objects. More...
 
wxPoint getLocation (TRACK *aTrack, BOARD_ITEM *aConflitItem, const SEG &aConflictSeg) const
 
bool testNetClasses ()
 Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings. More...
 
void testTracks (wxWindow *aActiveWindow, bool aShowProgressBar)
 Perform the DRC on all tracks. More...
 
void testPad2Pad ()
 
void testDrilledHoles ()
 
void testUnconnected ()
 
void testZones ()
 
void testKeepoutAreas ()
 
void testCopperTextItem (BOARD_ITEM *aTextItem)
 
void testCopperDrawItem (DRAWSEGMENT *aDrawing)
 
void testCopperTextAndGraphics ()
 
void testDisabledLayers ()
 

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

More...
 
void testOutline ()
 Test that the board outline is contiguous and composed of valid elements. More...
 
bool doNetClass (const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
 
bool doPadToPadsDrc (D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
 Test the clearance between aRefPad and other pads. More...
 
void doTrackDrc (TRACK *aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterator aEndIt, bool aTestZones)
 Test the current segment. More...
 
void doOverlappingCourtyardsDrc ()
 Test for footprint courtyard overlaps. More...
 
bool checkClearancePadToPad (D_PAD *aRefPad, D_PAD *aPad)
 
bool checkClearanceSegmToPad (const D_PAD *aPad, int aSegmentWidth, int aMinDist)
 Check the distance from a pad to segment. More...
 
bool checkLine (wxPoint aSegStart, wxPoint aSegEnd)
 Function checkLine (helper function used in drc calculations to see if one track is in contact with another track). More...
 

Static Private Member Functions

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

Private Attributes

bool m_doPad2PadTest
 
bool m_doUnconnectedTest
 
bool m_doZonesTest
 
bool m_doKeepoutTest
 
bool m_refillZones
 
bool m_reportAllTrackErrors
 
bool m_testFootprints
 
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
 
BOARDm_pcb
 
SHAPE_POLY_SET m_board_outlines
 
DIALOG_DRCm_drcDialog
 
std::vector< DRC_ITEM * > m_unconnected
 
std::vector< DRC_ITEM * > m_footprints
 
bool m_drcRun
 
bool m_footprintsTested
 

Friends

class DIALOG_DRC
 

Detailed Description

Design Rule Checker object that performs all the DRC tests.

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

Definition at line 133 of file drc.h.

Member Enumeration Documentation

◆ INTERACTIVE_PLACEMENT_OPTIONS

Enumerator
IPO_ROTATE 
IPO_FLIP 
IPO_SINGLE_CLICK 
IPO_REPEAT 

Definition at line 113 of file pcb_tool_base.h.

◆ RESET_REASON

enum TOOL_BASE::RESET_REASON
inherited

Determines the reason of reset for a tool

Enumerator
RUN 

Tool is invoked after being inactive.

MODEL_RELOAD 

Model changes (required full reload)

GAL_SWITCH 

Rendering engine changes.

Definition at line 78 of file tool_base.h.

79  {
80  RUN,
81  MODEL_RELOAD,
82  GAL_SWITCH
83  };
Model changes (required full reload)
Definition: tool_base.h:81
Tool is invoked after being inactive.
Definition: tool_base.h:80
Rendering engine changes.
Definition: tool_base.h:82

Constructor & Destructor Documentation

◆ DRC()

DRC::DRC ( )

Definition at line 58 of file pcbnew/drc/drc.cpp.

58  :
59  PCB_TOOL_BASE( "pcbnew.DRCTool" ),
60  m_pcbEditorFrame( nullptr ),
61  m_pcb( nullptr ),
62  m_drcDialog( nullptr )
63 {
64  // establish initial values for everything:
65  m_doPad2PadTest = true; // enable pad to pad clearance tests
66  m_doUnconnectedTest = true; // enable unconnected tests
67  m_doZonesTest = false; // disable zone to items clearance tests
68  m_doKeepoutTest = true; // enable keepout areas to items clearance tests
69  m_refillZones = false; // Only fill zones if requested by user.
70  m_reportAllTrackErrors = false;
71  m_testFootprints = false;
72 
73  m_drcRun = false;
74  m_footprintsTested = false;
75 
76  m_segmAngle = 0;
77  m_segmLength = 0;
78 
79  m_xcliplo = 0;
80  m_ycliplo = 0;
81  m_xcliphi = 0;
82  m_ycliphi = 0;
83 }
bool m_refillZones
Definition: drc.h:151
int m_ycliplo
Definition: drc.h:174
int m_ycliphi
Definition: drc.h:176
int m_segmLength
Definition: drc.h:168
BOARD * m_pcb
Definition: drc.h:179
bool m_testFootprints
Definition: drc.h:153
bool m_doKeepoutTest
Definition: drc.h:150
bool m_doZonesTest
Definition: drc.h:149
bool m_reportAllTrackErrors
Definition: drc.h:152
bool m_drcRun
Definition: drc.h:185
int m_xcliphi
Definition: drc.h:175
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
bool m_doPad2PadTest
Definition: drc.h:147
PCB_TOOL_BASE(TOOL_ID aId, const std::string &aName)
Constructor.
Definition: pcb_tool_base.h:75
bool m_footprintsTested
Definition: drc.h:186
DIALOG_DRC * m_drcDialog
Definition: drc.h:181
int m_xcliplo
Definition: drc.h:173
bool m_doUnconnectedTest
Definition: drc.h:148
double m_segmAngle
Definition: drc.h:167

References m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_doZonesTest, m_drcRun, m_footprintsTested, m_refillZones, m_reportAllTrackErrors, m_segmAngle, m_segmLength, m_testFootprints, m_xcliphi, m_xcliplo, m_ycliphi, and m_ycliplo.

◆ ~DRC()

DRC::~DRC ( )

Definition at line 86 of file pcbnew/drc/drc.cpp.

87 {
88  for( DRC_ITEM* unconnectedItem : m_unconnected )
89  delete unconnectedItem;
90 
91  for( DRC_ITEM* footprintItem : m_footprints )
92  delete footprintItem;
93 }
std::vector< DRC_ITEM * > m_footprints
Definition: drc.h:184
std::vector< DRC_ITEM * > m_unconnected
Definition: drc.h:183

References m_footprints, and m_unconnected.

Member Function Documentation

◆ Activate()

void TOOL_INTERACTIVE::Activate ( )
inherited

Function Activate() Runs the tool.

After activation, the tool starts receiving events until it is finished.

Definition at line 51 of file tool_interactive.cpp.

52 {
54 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
TOOL_ID m_toolId
Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
Definition: tool_base.h:213
bool InvokeTool(TOOL_ID aToolId)
Function InvokeTool() Calls a tool by sending a tool activation event to tool of given ID.

References TOOL_MANAGER::InvokeTool(), TOOL_BASE::m_toolId, and TOOL_BASE::m_toolMgr.

Referenced by AUTOPLACE_TOOL::autoplace(), EDIT_TOOL::copyToClipboard(), LIB_EDIT_TOOL::DeleteItemCursor(), SCH_EDIT_TOOL::DeleteItemCursor(), PCBNEW_CONTROL::DeleteItemCursor(), SCH_LINE_WIRE_BUS_TOOL::doDrawSegments(), PCB_TOOL_BASE::doInteractiveItemPlacement(), DRAWING_TOOL::DrawArc(), DRAWING_TOOL::DrawCircle(), DRAWING_TOOL::DrawDimension(), DRAWING_TOOL::DrawLine(), MICROWAVE_TOOL::drawMicrowaveInductor(), LIB_DRAWING_TOOLS::DrawShape(), SCH_DRAWING_TOOLS::DrawSheet(), DRAWING_TOOL::DrawZone(), PCB_EDITOR_CONTROL::DrillOrigin(), PAD_TOOL::EnumeratePads(), PCBNEW_CONTROL::GridSetOrigin(), SCH_EDITOR_CONTROL::HighlightNetCursor(), PCB_INSPECTION_TOOL::HighlightNetTool(), ROUTER_TOOL::InlineBreakTrack(), ROUTER_TOOL::InlineDrag(), PCB_INSPECTION_TOOL::LocalRatsnestTool(), SCH_MOVE_TOOL::Main(), EE_POINT_EDITOR::Main(), LIB_MOVE_TOOL::Main(), PCBNEW_PICKER_TOOL::Main(), PICKER_TOOL::Main(), ROUTER_TOOL::MainLoop(), LENGTH_TUNER_TOOL::MainLoop(), CVPCB_FOOTPRINT_VIEWER_SELECTION_TOOL::MeasureTool(), GERBVIEW_SELECTION_TOOL::MeasureTool(), EDIT_TOOL::MeasureTool(), EDIT_TOOL::Move(), LIB_TREE::onContextMenu(), POINT_EDITOR::OnSelectionChange(), LIB_DRAWING_TOOLS::PlaceAnchor(), SCH_DRAWING_TOOLS::PlaceComponent(), SCH_DRAWING_TOOLS::PlaceImage(), DRAWING_TOOL::PlaceImportedGraphics(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), DRAWING_TOOL::PlaceText(), EDIT_TOOL::Remove(), POSITION_RELATIVE_TOOL::SelectPositionRelativeItem(), DRAWING_TOOL::SetAnchor(), ShowDRCDialog(), SCH_DRAWING_TOOLS::SingleClickPlace(), LIB_DRAWING_TOOLS::TwoClickPlace(), SCH_DRAWING_TOOLS::TwoClickPlace(), and SCH_LINE_WIRE_BUS_TOOL::UnfoldBus().

◆ addMarkerToPcb()

void DRC::addMarkerToPcb ( MARKER_PCB aMarker)
private

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

Definition at line 161 of file pcbnew/drc/drc.cpp.

162 {
163  BOARD_COMMIT commit( m_pcbEditorFrame );
164  commit.Add( aMarker );
165  commit.Push( wxEmptyString, false, false );
166 }
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178

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

Referenced by doNetClass(), doOverlappingCourtyardsDrc(), doPadToPadsDrc(), doTrackDrc(), testCopperDrawItem(), testCopperTextItem(), testDisabledLayers(), testDrilledHoles(), testKeepoutAreas(), testOutline(), testZones(), and TestZoneToZoneOutlines().

◆ attachManager()

void TOOL_BASE::attachManager ( TOOL_MANAGER aManager)
protectedinherited

Function attachManager()

Sets the TOOL_MANAGER the tool will belong to. Called by TOOL_MANAGER::RegisterTool()

Definition at line 60 of file tool_base.cpp.

61 {
62  m_toolMgr = aManager;
63 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218

References TOOL_BASE::m_toolMgr.

Referenced by TOOL_MANAGER::RegisterTool().

◆ board()

BOARD* PCB_TOOL_BASE::board ( ) const
inlineprotectedinherited

Definition at line 155 of file pcb_tool_base.h.

155 { return getModel<BOARD>(); }

Referenced by PCBNEW_CONTROL::AppendBoard(), AUTOPLACE_TOOL::autoplace(), PCB_INSPECTION_TOOL::calculateSelectionRatsnest(), EDIT_TOOL::ChangeTrackWidth(), ZONE_FILLER_TOOL::CheckAllZones(), checkClearancePadToPad(), checkClearanceSegmToPad(), PCB_INSPECTION_TOOL::ClearHighlight(), DRAWING_TOOL::constrainDimension(), EDIT_TOOL::copyToClipboard(), MICROWAVE_TOOL::createInductorBetween(), MODULE_EDITOR_TOOLS::CreatePadFromShapes(), ROUTER_TOOL::CustomTrackWidthDialog(), PCBNEW_CONTROL::DeleteItemCursor(), PCB_TOOL_BASE::doInteractiveItemPlacement(), DRAWING_TOOL::drawArc(), DRAWING_TOOL::DrawDimension(), DRAWING_TOOL::drawSegment(), PAD_TOOL::EnumeratePads(), MODULE_EDITOR_TOOLS::ExplodePadToShapes(), ZONE_FILLER_TOOL::FillAllZones(), SELECTION_TOOL::filterSelection(), SELECTION_TOOL::getCollectorsGuide(), PCBNEW_CONTROL::GraphicDisplayMode(), PCB_INSPECTION_TOOL::highlightNet(), PCBNEW_CONTROL::LayerNext(), PCBNEW_CONTROL::LayerPrev(), PCB_INSPECTION_TOOL::LocalRatsnestTool(), PCB_TOOL_BASE::module(), PCBNEW_CONTROL::ModuleEdgeOutlines(), PCBNEW_CONTROL::ModuleTextOutlines(), ROUTER_TOOL::onTrackViaSizeChanged(), ROUTER_TOOL::onViaCommand(), PCBNEW_CONTROL::PadDisplayMode(), PCBNEW_CONTROL::Paste(), PCBNEW_CONTROL::placeBoardItems(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), DRAWING_TOOL::PlaceText(), ROUTER_TOOL::prepareInteractive(), SELECTION_TOOL::RebuildSelection(), PNS::TOOL_BASE::Reset(), PCBNEW_CONTROL::Reset(), SELECTION_TOOL::Selectable(), SELECTION_TOOL::selectAllItemsOnNet(), SELECTION_TOOL::selectAllItemsOnSheet(), SELECTION_TOOL::selectConnectedTracks(), SELECTION_TOOL::selectPoint(), testDisabledLayers(), TestZoneToZoneOutlines(), PCBNEW_CONTROL::TrackDisplayMode(), POINT_EDITOR::updateItem(), PCBNEW_CONTROL::ViaDisplayMode(), PCBNEW_CONTROL::ZoneDisplayMode(), ZONE_FILLER_TOOL::ZoneFill(), PCB_EDITOR_CONTROL::ZoneMerge(), and ZONE_FILLER_TOOL::ZoneUnfillAll().

◆ canvas()

◆ checkClearancePadToPad()

bool DRC::checkClearancePadToPad ( D_PAD aRefPad,
D_PAD aPad 
)
private
Parameters
aRefPadThe reference pad to check
aPadAnother pad to check against
Returns
bool - true if clearance between aRefPad and aPad is >= dist_min, else false

Definition at line 712 of file drc_clearance_test_functions.cpp.

713 {
714  int dist;
715  double pad_angle;
716 
717  // Get the clearance between the 2 pads. this is the min distance between aRefPad and aPad
718  int dist_min = aRefPad->GetClearance( aPad );
719 
720  // relativePadPos is the aPad shape position relative to the aRefPad shape position
721  wxPoint relativePadPos = aPad->ShapePos() - aRefPad->ShapePos();
722 
723  dist = KiROUND( EuclideanNorm( relativePadPos ) );
724 
725  // Quick test: Clearance is OK if the bounding circles are further away than "dist_min"
726  int delta = dist - aRefPad->GetBoundingRadius() - aPad->GetBoundingRadius();
727 
728  if( delta >= dist_min )
729  return true;
730 
731  /* Here, pads are near and DRC depend on the pad shapes
732  * We must compare distance using a fine shape analysis
733  * Because a circle or oval shape is the easier shape to test, try to have
734  * aRefPad shape type = PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
735  * if aRefPad = TRAP. and aPad = RECT, also swap pads
736  * Swap aRefPad and aPad if needed
737  */
738  bool swap_pads;
739  swap_pads = false;
740 
741  // swap pads to make comparisons easier
742  // Note also a ROUNDRECT pad with a corner radius = r can be considered as
743  // a smaller RECT (size - 2*r) with a clearance increased by r
744  // priority is aRefPad = ROUND then OVAL then RECT/ROUNDRECT then other
745  if( aRefPad->GetShape() != aPad->GetShape() && aRefPad->GetShape() != PAD_SHAPE_CIRCLE )
746  {
747  // pad ref shape is here oval, rect, roundrect, chamfered rect, trapezoid or custom
748  switch( aPad->GetShape() )
749  {
750  case PAD_SHAPE_CIRCLE:
751  swap_pads = true;
752  break;
753 
754  case PAD_SHAPE_OVAL:
755  swap_pads = true;
756  break;
757 
758  case PAD_SHAPE_RECT:
759  case PAD_SHAPE_ROUNDRECT:
760  if( aRefPad->GetShape() != PAD_SHAPE_OVAL )
761  swap_pads = true;
762  break;
763 
764  case PAD_SHAPE_TRAPEZOID:
766  case PAD_SHAPE_CUSTOM:
767  break;
768  }
769  }
770 
771  if( swap_pads )
772  {
773  std::swap( aRefPad, aPad );
774  relativePadPos = -relativePadPos;
775  }
776 
777  // corners of aRefPad (used only for rect/roundrect/trap pad)
778  wxPoint polyref[4];
779  // corners of aRefPad (used only for custom pad)
780  SHAPE_POLY_SET polysetref;
781 
782  // corners of aPad (used only for rect/roundrect/trap pad)
783  wxPoint polycompare[4];
784  // corners of aPad (used only custom pad)
785  SHAPE_POLY_SET polysetcompare;
786 
787  /* Because pad exchange, aRefPad shape is PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL,
788  * if one of the 2 pads was a PAD_SHAPE_CIRCLE or PAD_SHAPE_OVAL.
789  * Therefore, if aRefPad is a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID,
790  * aPad is also a PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT or a PAD_SHAPE_TRAPEZOID
791  */
792  bool diag = true;
793 
794  switch( aRefPad->GetShape() )
795  {
796  case PAD_SHAPE_CIRCLE:
797 
798  /* One can use checkClearanceSegmToPad to test clearance
799  * aRefPad is like a track segment with a null length and a witdth = GetSize().x
800  */
801  m_segmLength = 0;
802  m_segmAngle = 0;
803 
804  m_segmEnd.x = m_segmEnd.y = 0;
805 
806  m_padToTestPos = relativePadPos;
807  diag = checkClearanceSegmToPad( aPad, aRefPad->GetSize().x, dist_min );
808  break;
809 
810  case PAD_SHAPE_TRAPEZOID:
811  case PAD_SHAPE_ROUNDRECT:
813  case PAD_SHAPE_RECT:
814  case PAD_SHAPE_CUSTOM:
815  // pad_angle = pad orient relative to the aRefPad orient
816  pad_angle = aRefPad->GetOrientation() + aPad->GetOrientation();
817  NORMALIZE_ANGLE_POS( pad_angle );
818 
819  if( aRefPad->GetShape() == PAD_SHAPE_ROUNDRECT )
820  {
821  int padRadius = aRefPad->GetRoundRectCornerRadius();
822  dist_min += padRadius;
823  GetRoundRectCornerCenters( polyref, padRadius, wxPoint( 0, 0 ), aRefPad->GetSize(),
824  aRefPad->GetOrientation() );
825  }
826  else if( aRefPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
827  {
828  auto board = aRefPad->GetBoard();
829  int maxError = ARC_HIGH_DEF;
830 
831  if( board )
832  maxError = board->GetDesignSettings().m_MaxError;
833 
834  // The reference pad can be rotated. calculate the rotated
835  // coordinates ( note, the ref pad position is the origin of
836  // coordinates for this drc test)
837  int padRadius = aRefPad->GetRoundRectCornerRadius();
838  TransformRoundChamferedRectToPolygon( polysetref, wxPoint( 0, 0 ), aRefPad->GetSize(),
839  aRefPad->GetOrientation(),
840  padRadius, aRefPad->GetChamferRectRatio(),
841  aRefPad->GetChamferPositions(), maxError );
842  }
843  else if( aRefPad->GetShape() == PAD_SHAPE_CUSTOM )
844  {
845  polysetref.Append( aRefPad->GetCustomShapeAsPolygon() );
846 
847  // The reference pad can be rotated. calculate the rotated
848  // coordiantes ( note, the ref pad position is the origin of
849  // coordinates for this drc test)
850  aRefPad->CustomShapeAsPolygonToBoardPosition( &polysetref, wxPoint( 0, 0 ),
851  aRefPad->GetOrientation() );
852  }
853  else
854  {
855  // BuildPadPolygon has meaning for rect a trapeziod shapes
856  // and returns the 4 corners
857  aRefPad->BuildPadPolygon( polyref, wxSize( 0, 0 ), aRefPad->GetOrientation() );
858  }
859 
860  switch( aPad->GetShape() )
861  {
862  case PAD_SHAPE_ROUNDRECT:
863  case PAD_SHAPE_RECT:
865  case PAD_SHAPE_TRAPEZOID:
866  case PAD_SHAPE_CUSTOM:
867  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
868  {
869  int padRadius = aPad->GetRoundRectCornerRadius();
870  dist_min += padRadius;
871  GetRoundRectCornerCenters( polycompare, padRadius, relativePadPos, aPad->GetSize(),
872  aPad->GetOrientation() );
873  }
874  else if( aPad->GetShape() == PAD_SHAPE_CHAMFERED_RECT )
875  {
876  auto board = aRefPad->GetBoard();
877  int maxError = ARC_HIGH_DEF;
878 
879  if( board )
880  maxError = board->GetDesignSettings().m_MaxError;
881 
882  // The reference pad can be rotated. calculate the rotated
883  // coordinates ( note, the ref pad position is the origin of
884  // coordinates for this drc test)
885  int padRadius = aPad->GetRoundRectCornerRadius();
886  TransformRoundChamferedRectToPolygon( polysetcompare, relativePadPos,
887  aPad->GetSize(), aPad->GetOrientation(),
888  padRadius, aPad->GetChamferRectRatio(),
889  aPad->GetChamferPositions(), maxError );
890  }
891  else if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
892  {
893  polysetcompare.Append( aPad->GetCustomShapeAsPolygon() );
894 
895  // The pad to compare can be rotated. calculate the rotated
896  // coordinattes ( note, the pad to compare position
897  // is the relativePadPos for this drc test
898  aPad->CustomShapeAsPolygonToBoardPosition( &polysetcompare, relativePadPos,
899  aPad->GetOrientation() );
900  }
901  else
902  {
903  aPad->BuildPadPolygon( polycompare, wxSize( 0, 0 ), aPad->GetOrientation() );
904 
905  // Move aPad shape to relativePadPos
906  for( int ii = 0; ii < 4; ii++ )
907  polycompare[ii] += relativePadPos;
908  }
909  // And now test polygons: We have 3 cases:
910  // one poly is complex and the other is basic (has only 4 corners)
911  // both polys are complex
912  // both polys are basic (have only 4 corners) the most usual case
913  if( polysetref.OutlineCount() && polysetcompare.OutlineCount() == 0)
914  {
915  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
916  // And now test polygons:
917  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
918  polycompare, 4, dist_min ) ) // Therefore error
919  diag = false;
920  }
921  else if( polysetref.OutlineCount() == 0 && polysetcompare.OutlineCount())
922  {
923  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
924  // And now test polygons:
925  if( !poly2polyDRC( (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(),
926  polyref, 4, dist_min ) ) // Therefore error
927  diag = false;
928  }
929  else if( polysetref.OutlineCount() && polysetcompare.OutlineCount() )
930  {
931  const SHAPE_LINE_CHAIN& refpoly = polysetref.COutline( 0 );
932  const SHAPE_LINE_CHAIN& cmppoly = polysetcompare.COutline( 0 );
933 
934  // And now test polygons:
935  if( !poly2polyDRC( (wxPoint*) &refpoly.CPoint( 0 ), refpoly.PointCount(),
936  (wxPoint*) &cmppoly.CPoint( 0 ), cmppoly.PointCount(),
937  dist_min ) ) // Therefore error
938  diag = false;
939  }
940  else
941  {
942  if( !poly2polyDRC( polyref, 4, polycompare, 4, dist_min ) ) // Therefore error
943  diag = false;
944  }
945  break;
946 
947  default:
948  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unexpected pad shape %d" ), aPad->GetShape() );
949  break;
950  }
951  break;
952 
953  case PAD_SHAPE_OVAL: /* an oval pad is like a track segment */
954  {
955  /* Create a track segment with same dimensions as the oval aRefPad
956  * and use checkClearanceSegmToPad function to test aPad to aRefPad clearance
957  */
958  int segm_width;
959  m_segmAngle = aRefPad->GetOrientation(); // Segment orient.
960 
961  if( aRefPad->GetSize().y < aRefPad->GetSize().x ) // Build an horizontal equiv segment
962  {
963  segm_width = aRefPad->GetSize().y;
964  m_segmLength = aRefPad->GetSize().x - aRefPad->GetSize().y;
965  }
966  else // Vertical oval: build an horizontal equiv segment and rotate 90.0 deg
967  {
968  segm_width = aRefPad->GetSize().x;
969  m_segmLength = aRefPad->GetSize().y - aRefPad->GetSize().x;
970  m_segmAngle += 900;
971  }
972 
973  /* the start point must be 0,0 and currently relativePadPos
974  * is relative the center of pad coordinate */
975  wxPoint segstart;
976  segstart.x = -m_segmLength / 2; // Start point coordinate of the horizontal equivalent segment
977 
978  RotatePoint( &segstart, m_segmAngle ); // actual start point coordinate of the equivalent segment
979  // Calculate segment end position relative to the segment origin
980  m_segmEnd.x = -2 * segstart.x;
981  m_segmEnd.y = -2 * segstart.y;
982 
983  // Recalculate the equivalent segment angle in 0,1 degrees
984  // to prepare a call to checkClearanceSegmToPad()
986 
987  // move pad position relative to the segment origin
988  m_padToTestPos = relativePadPos - segstart;
989 
990  // Use segment to pad check to test the second pad:
991  diag = checkClearanceSegmToPad( aPad, segm_width, dist_min );
992  break;
993  }
994 
995  default:
996  wxLogDebug( wxT( "DRC::checkClearancePadToPad: unknown pad shape" ) );
997  break;
998  }
999 
1000  return diag;
1001 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:128
bool poly2polyDRC(wxPoint *aTref, int aTrefCount, wxPoint *aTtest, int aTtestCount, int aDist)
compare 2 convex polygons and return true if distance > aDist (if no error DRC) i....
int OutlineCount() const
Returns the number of outlines in the set
static const int dist[10][10]
Definition: ar_matrix.cpp:326
BOARD * board() const
int m_segmLength
Definition: drc.h:168
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:257
int PointCount() const
Function PointCount()
wxPoint m_padToTestPos
Definition: drc.h:159
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:724
const VECTOR2I & CPoint(int aIndex) const
Function Point()
SHAPE_POLY_SET.
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:701
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:653
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aApproxErrorMax, int aMinSegPerCircleCount=16)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Check the distance from a pad to segment.
wxPoint m_segmEnd
Definition: drc.h:160
SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:426
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
wxPoint ShapePos() const
Definition: class_pad.cpp:570
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:378
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:577
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...
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:237
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
const wxSize & GetSize() const
Definition: class_pad.h:300
double m_segmAngle
Definition: drc.h:167
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)

References SHAPE_POLY_SET::Append(), ArcTangente(), PCB_TOOL_BASE::board(), D_PAD::BuildPadPolygon(), checkClearanceSegmToPad(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), D_PAD::CustomShapeAsPolygonToBoardPosition(), dist, EuclideanNorm(), BOARD_ITEM::GetBoard(), D_PAD::GetBoundingRadius(), D_PAD::GetChamferPositions(), D_PAD::GetChamferRectRatio(), D_PAD::GetClearance(), D_PAD::GetCustomShapeAsPolygon(), BOARD::GetDesignSettings(), D_PAD::GetOrientation(), GetRoundRectCornerCenters(), D_PAD::GetRoundRectCornerRadius(), D_PAD::GetShape(), D_PAD::GetSize(), KiROUND(), BOARD_DESIGN_SETTINGS::m_MaxError, m_padToTestPos, m_segmAngle, m_segmEnd, m_segmLength, NORMALIZE_ANGLE_POS(), SHAPE_POLY_SET::OutlineCount(), PAD_SHAPE_CHAMFERED_RECT, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), poly2polyDRC(), RotatePoint(), D_PAD::ShapePos(), TransformRoundChamferedRectToPolygon(), wxPoint::x, and wxPoint::y.

Referenced by doPadToPadsDrc().

◆ checkClearanceSegmToPad()

bool DRC::checkClearanceSegmToPad ( const D_PAD aPad,
int  aSegmentWidth,
int  aMinDist 
)
private

Check the distance from a pad to segment.

This function uses several instance variable not passed in: m_segmLength = length of the segment being tested m_segmAngle = angle of the segment with the X axis; m_segmEnd = end coordinate of the segment m_padToTestPos = position of pad relative to the origin of segment

Parameters
aPadIs the pad involved in the check
aSegmentWidthwidth of the segment to test
aMinDistIs the minimum clearance needed
Returns
true distance >= dist_min, false if distance < dist_min

Definition at line 1009 of file drc_clearance_test_functions.cpp.

1010 {
1011  // Note:
1012  // we are using a horizontal segment for test, because we know here
1013  // only the length and orientation+ of the segment
1014  // Therefore the coordinates of the shape of pad to compare
1015  // must be calculated in a axis system rotated by m_segmAngle
1016  // and centered to the segment origin, before they can be tested
1017  // against the segment
1018  // We are using:
1019  // m_padToTestPos the position of the pad shape in this axis system
1020  // m_segmAngle the axis system rotation
1021 
1022  int segmHalfWidth = aSegmentWidth / 2;
1023  int distToLine = segmHalfWidth + aMinDist;
1024 
1025  wxSize padHalfsize; // half dimension of the pad
1026 
1027  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
1028  {
1029  // For a custom pad, the pad size has no meaning, we only can
1030  // use the bounding radius
1031  padHalfsize.x = padHalfsize.y = aPad->GetBoundingRadius();
1032  }
1033  else
1034  {
1035  padHalfsize = aPad->GetSize() / 2;
1036  }
1037 
1038  if( aPad->GetShape() == PAD_SHAPE_TRAPEZOID ) // The size is bigger, due to GetDelta() extra size
1039  {
1040  padHalfsize.x += std::abs(aPad->GetDelta().y) / 2; // Remember: GetDelta().y is the GetSize().x change
1041  padHalfsize.y += std::abs(aPad->GetDelta().x) / 2; // Remember: GetDelta().x is the GetSize().y change
1042  }
1043 
1044  if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
1045  {
1046  /* Easy case: just test the distance between segment and pad centre
1047  * calculate pad coordinates in the X,Y axis with X axis = segment to test
1048  */
1050  return checkMarginToCircle( m_padToTestPos, distToLine + padHalfsize.x, m_segmLength );
1051  }
1052 
1053  /* calculate the bounding box of the pad, including the clearance and the segment width
1054  * if the line from 0 to m_segmEnd does not intersect this bounding box,
1055  * the clearance is always OK
1056  * But if intersect, a better analysis of the pad shape must be done.
1057  */
1058  m_xcliplo = m_padToTestPos.x - distToLine - padHalfsize.x;
1059  m_ycliplo = m_padToTestPos.y - distToLine - padHalfsize.y;
1060  m_xcliphi = m_padToTestPos.x + distToLine + padHalfsize.x;
1061  m_ycliphi = m_padToTestPos.y + distToLine + padHalfsize.y;
1062 
1063  wxPoint startPoint( 0, 0 );
1064  wxPoint endPoint = m_segmEnd;
1065 
1066  double orient = aPad->GetOrientation();
1067 
1068  RotatePoint( &startPoint, m_padToTestPos, -orient );
1069  RotatePoint( &endPoint, m_padToTestPos, -orient );
1070 
1071  if( checkLine( startPoint, endPoint ) )
1072  return true;
1073 
1074  /* segment intersects the bounding box. But there is not always a DRC error.
1075  * A fine analysis of the pad shape must be done.
1076  */
1077  switch( aPad->GetShape() )
1078  {
1079  case PAD_SHAPE_CIRCLE:
1080  // This case was already tested, so it cannot be found here.
1081  // it is here just to avoid compil warning, and to remember
1082  // it is already tested.
1083  return false;
1084 
1085  case PAD_SHAPE_OVAL:
1086  {
1087  /* an oval is a complex shape, but is a rectangle and 2 circles
1088  * these 3 basic shapes are more easy to test.
1089  *
1090  * In calculations we are using a vertical or horizontal oval shape
1091  * (i.e. a vertical or horizontal rounded segment)
1092  */
1093  wxPoint cstart = m_padToTestPos;
1094  wxPoint cend = m_padToTestPos; // center of each circle
1095  int delta = std::abs( padHalfsize.y - padHalfsize.x );
1096  int radius = std::min( padHalfsize.y, padHalfsize.x );
1097 
1098  if( padHalfsize.x > padHalfsize.y ) // horizontal equivalent segment
1099  {
1100  cstart.x -= delta;
1101  cend.x += delta;
1102  // Build the rectangular clearance area between the two circles
1103  // the rect starts at cstart.x and ends at cend.x and its height
1104  // is (radius + distToLine)*2
1105  m_xcliplo = cstart.x;
1106  m_ycliplo = cstart.y - radius - distToLine;
1107  m_xcliphi = cend.x;
1108  m_ycliphi = cend.y + radius + distToLine;
1109  }
1110  else // vertical equivalent segment
1111  {
1112  cstart.y -= delta;
1113  cend.y += delta;
1114  // Build the rectangular clearance area between the two circles
1115  // the rect starts at cstart.y and ends at cend.y and its width
1116  // is (radius + distToLine)*2
1117  m_xcliplo = cstart.x - distToLine - radius;
1118  m_ycliplo = cstart.y;
1119  m_xcliphi = cend.x + distToLine + radius;
1120  m_ycliphi = cend.y;
1121  }
1122 
1123  // Test the rectangular clearance area between the two circles (the rounded ends)
1124  // If the segment legth is zero, only check the endpoints, skip the rectangle
1125  if( m_segmLength && !checkLine( startPoint, endPoint ) )
1126  {
1127  return false;
1128  }
1129 
1130  // test the first end
1131  // Calculate the actual position of the circle, given the pad orientation:
1132  RotatePoint( &cstart, m_padToTestPos, orient );
1133 
1134  // Calculate the actual position of the circle in the new X,Y axis, relative
1135  // to the segment:
1136  RotatePoint( &cstart, m_segmAngle );
1137 
1138  if( !checkMarginToCircle( cstart, radius + distToLine, m_segmLength ) )
1139  {
1140  return false;
1141  }
1142 
1143  // test the second end
1144  RotatePoint( &cend, m_padToTestPos, orient );
1145  RotatePoint( &cend, m_segmAngle );
1146 
1147  if( !checkMarginToCircle( cend, radius + distToLine, m_segmLength ) )
1148  {
1149  return false;
1150  }
1151  }
1152  break;
1153 
1154  case PAD_SHAPE_ROUNDRECT:
1155  {
1156  // a round rect is a smaller rect, with a clearance augmented by the corners radius
1157  int r = aPad->GetRoundRectCornerRadius();
1158  padHalfsize.x -= r;
1159  padHalfsize.y -= r;
1160  distToLine += r;
1161  }
1162  // Fall through
1163  case PAD_SHAPE_RECT:
1164  // the area to test is a rounded rectangle.
1165  // this can be done by testing 2 rectangles and 4 circles (the corners)
1166 
1167  // Testing the first rectangle dimx + distToLine, dimy:
1168  m_xcliplo = m_padToTestPos.x - padHalfsize.x - distToLine;
1169  m_ycliplo = m_padToTestPos.y - padHalfsize.y;
1170  m_xcliphi = m_padToTestPos.x + padHalfsize.x + distToLine;
1171  m_ycliphi = m_padToTestPos.y + padHalfsize.y;
1172 
1173  if( !checkLine( startPoint, endPoint ) )
1174  return false;
1175 
1176  // Testing the second rectangle dimx , dimy + distToLine
1177  m_xcliplo = m_padToTestPos.x - padHalfsize.x;
1178  m_ycliplo = m_padToTestPos.y - padHalfsize.y - distToLine;
1179  m_xcliphi = m_padToTestPos.x + padHalfsize.x;
1180  m_ycliphi = m_padToTestPos.y + padHalfsize.y + distToLine;
1181 
1182  if( !checkLine( startPoint, endPoint ) )
1183  return false;
1184 
1185  // testing the 4 circles which are the clearance area of each corner:
1186 
1187  // testing the left top corner of the rectangle
1188  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1189  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1190  RotatePoint( &startPoint, m_padToTestPos, orient );
1191  RotatePoint( &startPoint, m_segmAngle );
1192 
1193  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1194  return false;
1195 
1196  // testing the right top corner of the rectangle
1197  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1198  startPoint.y = m_padToTestPos.y - padHalfsize.y;
1199  RotatePoint( &startPoint, m_padToTestPos, orient );
1200  RotatePoint( &startPoint, m_segmAngle );
1201 
1202  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1203  return false;
1204 
1205  // testing the left bottom corner of the rectangle
1206  startPoint.x = m_padToTestPos.x - padHalfsize.x;
1207  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1208  RotatePoint( &startPoint, m_padToTestPos, orient );
1209  RotatePoint( &startPoint, m_segmAngle );
1210 
1211  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1212  return false;
1213 
1214  // testing the right bottom corner of the rectangle
1215  startPoint.x = m_padToTestPos.x + padHalfsize.x;
1216  startPoint.y = m_padToTestPos.y + padHalfsize.y;
1217  RotatePoint( &startPoint, m_padToTestPos, orient );
1218  RotatePoint( &startPoint, m_segmAngle );
1219 
1220  if( !checkMarginToCircle( startPoint, distToLine, m_segmLength ) )
1221  return false;
1222 
1223  break;
1224 
1225  case PAD_SHAPE_TRAPEZOID:
1226  {
1227  wxPoint poly[4];
1228  aPad->BuildPadPolygon( poly, wxSize( 0, 0 ), orient );
1229 
1230  // Move shape to m_padToTestPos
1231  for( int ii = 0; ii < 4; ii++ )
1232  {
1233  poly[ii] += m_padToTestPos;
1234  RotatePoint( &poly[ii], m_segmAngle );
1235  }
1236 
1237  if( !poly2segmentDRC( poly, 4, wxPoint( 0, 0 ),
1238  wxPoint(m_segmLength,0), distToLine ) )
1239  return false;
1240  }
1241  break;
1242 
1243  case PAD_SHAPE_CUSTOM:
1244  {
1245  SHAPE_POLY_SET polyset;
1246  polyset.Append( aPad->GetCustomShapeAsPolygon() );
1247  // The pad can be rotated. calculate the coordinates
1248  // relatives to the segment being tested
1249  // Note, the pad position relative to the segment origin
1250  // is m_padToTestPos
1251  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1252  m_padToTestPos, orient );
1253 
1254  // Rotate all coordinates by m_segmAngle, because the segment orient
1255  // is m_segmAngle
1256  // we are using a horizontal segment for test, because we know here
1257  // only the lenght and orientation+ of the segment
1258  // therefore all coordinates of the pad to test must be rotated by
1259  // m_segmAngle (they are already relative to the segment origin)
1260  aPad->CustomShapeAsPolygonToBoardPosition( &polyset,
1261  wxPoint( 0, 0 ), m_segmAngle );
1262 
1263  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1264 
1265  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1266  refpoly.PointCount(),
1267  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1268  distToLine ) )
1269  return false;
1270  }
1271  break;
1272 
1274  {
1275  auto board = aPad->GetBoard();
1276  int maxError = ARC_HIGH_DEF;
1277 
1278  if( board )
1279  maxError = board->GetDesignSettings().m_MaxError;
1280 
1281  SHAPE_POLY_SET polyset;
1282  // The pad can be rotated. calculate the coordinates
1283  // relatives to the segment being tested
1284  // Note, the pad position relative to the segment origin
1285  // is m_padToTestPos
1286  int padRadius = aPad->GetRoundRectCornerRadius();
1288  aPad->GetOrientation(),
1289  padRadius, aPad->GetChamferRectRatio(),
1290  aPad->GetChamferPositions(), maxError );
1291  // Rotate also coordinates by m_segmAngle, because the segment orient
1292  // is m_segmAngle.
1293  // we are using a horizontal segment for test, because we know here
1294  // only the lenght and orientation of the segment
1295  // therefore all coordinates of the pad to test must be rotated by
1296  // m_segmAngle (they are already relative to the segment origin)
1297  polyset.Rotate( DECIDEG2RAD( -m_segmAngle ), VECTOR2I( 0, 0 ) );
1298 
1299  const SHAPE_LINE_CHAIN& refpoly = polyset.COutline( 0 );
1300 
1301  if( !poly2segmentDRC( (wxPoint*) &refpoly.CPoint( 0 ),
1302  refpoly.PointCount(),
1303  wxPoint( 0, 0 ), wxPoint(m_segmLength,0),
1304  distToLine ) )
1305  return false;
1306  }
1307  break;
1308  }
1309 
1310  return true;
1311 }
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 })
Function Rotate rotates all vertices by a given angle.
BOARD * board() const
int m_ycliplo
Definition: drc.h:174
int m_ycliphi
Definition: drc.h:176
bool poly2segmentDRC(wxPoint *aTref, int aTrefCount, wxPoint aSegStart, wxPoint aSegEnd, int aDist)
int m_segmLength
Definition: drc.h:168
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
int PointCount() const
Function PointCount()
wxPoint m_padToTestPos
Definition: drc.h:159
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:724
bool checkLine(wxPoint aSegStart, wxPoint aSegEnd)
Function checkLine (helper function used in drc calculations to see if one track is in contact with a...
const VECTOR2I & CPoint(int aIndex) const
Function Point()
SHAPE_POLY_SET.
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:701
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Check the distance from a point to a segment.
int GetBoundingRadius() const
Function GetBoundingRadius returns the radius of a minimum sized circle which fully encloses this pad...
Definition: class_pad.h:653
const wxSize & GetDelta() const
Definition: class_pad.h:303
int m_xcliphi
Definition: drc.h:175
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aApproxErrorMax, int aMinSegPerCircleCount=16)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
wxPoint m_segmEnd
Definition: drc.h:160
SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:426
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:378
double DECIDEG2RAD(double deg)
Definition: trigo.h:218
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:577
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:237
const wxSize & GetSize() const
Definition: class_pad.h:300
int m_xcliplo
Definition: drc.h:173
double m_segmAngle
Definition: drc.h:167
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)

References SHAPE_POLY_SET::Append(), PCB_TOOL_BASE::board(), D_PAD::BuildPadPolygon(), checkLine(), checkMarginToCircle(), SHAPE_POLY_SET::COutline(), SHAPE_LINE_CHAIN::CPoint(), D_PAD::CustomShapeAsPolygonToBoardPosition(), DECIDEG2RAD(), BOARD_ITEM::GetBoard(), D_PAD::GetBoundingRadius(), D_PAD::GetChamferPositions(), D_PAD::GetChamferRectRatio(), D_PAD::GetCustomShapeAsPolygon(), D_PAD::GetDelta(), BOARD::GetDesignSettings(), D_PAD::GetOrientation(), D_PAD::GetRoundRectCornerRadius(), D_PAD::GetShape(), D_PAD::GetSize(), BOARD_DESIGN_SETTINGS::m_MaxError, m_padToTestPos, m_segmAngle, m_segmEnd, m_segmLength, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, PAD_SHAPE_CHAMFERED_RECT, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, SHAPE_LINE_CHAIN::PointCount(), poly2segmentDRC(), SHAPE_POLY_SET::Rotate(), RotatePoint(), TransformRoundChamferedRectToPolygon(), wxPoint::x, and wxPoint::y.

Referenced by checkClearancePadToPad(), and doTrackDrc().

◆ checkLine()

bool DRC::checkLine ( wxPoint  aSegStart,
wxPoint  aSegEnd 
)
private

Function checkLine (helper function used in drc calculations to see if one track is in contact with another track).

Helper function checkLine Test if a line intersects a bounding box (a rectangle) The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi return true if the line from aSegStart to aSegEnd is outside the bounding box.

Test if a line intersects a bounding box (a rectangle) The rectangle is defined by m_xcliplo, m_ycliplo and m_xcliphi, m_ycliphi return true if the line from aSegStart to aSegEnd is outside the bounding box

Definition at line 1373 of file drc_clearance_test_functions.cpp.

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

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

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

◆ checkMarginToCircle()

bool DRC::checkMarginToCircle ( wxPoint  aCentre,
int  aRadius,
int  aLength 
)
staticprivate

Check the distance from a point to a segment.

Helper function checkMarginToCircle Check the distance between a circle (round pad, via or round end of track) and a segment.

The segment is expected starting at 0,0, and on the X axis (used to test DRC between a segment and a round pad, via or round end of a track

Parameters
aCentreThe coordinate of the circle's center
aRadiusA "keep out" radius centered over the circle
aLengthThe length of the segment (i.e. coordinate of end, because it is on the X axis)
Returns
bool - true if distance >= radius, else false when distance < aRadius

the segment is expected starting at 0,0, and on the X axis return true if distance >= aRadius

Definition at line 1320 of file drc_clearance_test_functions.cpp.

1321 {
1322  if( abs( aCentre.y ) >= aRadius ) // trivial case
1323  return true;
1324 
1325  // Here, distance between aCentre and X axis is < aRadius
1326  if( (aCentre.x > -aRadius ) && ( aCentre.x < (aLength + aRadius) ) )
1327  {
1328  if( (aCentre.x >= 0) && (aCentre.x <= aLength) )
1329  return false; // aCentre is between the starting point and the ending point of the segm
1330 
1331  if( aCentre.x > aLength ) // aCentre is after the ending point
1332  aCentre.x -= aLength; // move aCentre to the starting point of the segment
1333 
1334  if( EuclideanNorm( aCentre ) < aRadius )
1335  // distance between aCentre and the starting point or the ending point is < aRadius
1336  return false;
1337  }
1338 
1339  return true;
1340 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:128

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

Referenced by checkClearanceSegmToPad(), and doTrackDrc().

◆ controls()

◆ DestroyDRCDialog()

void DRC::DestroyDRCDialog ( int  aReason)

Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.

Parameters
aReasonIndication of which button was clicked to cause the destruction. if aReason == wxID_OK, design parameters values which can be entered from the dialog will bbe saved in design parameters list

Definition at line 169 of file pcbnew/drc/drc.cpp.

170 {
171  if( m_drcDialog )
172  {
173  m_drcDialog->Destroy();
174  m_drcDialog = nullptr;
175  }
176 }
DIALOG_DRC * m_drcDialog
Definition: drc.h:181

References m_drcDialog.

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

◆ displayOptions()

◆ doInteractiveItemPlacement()

void PCB_TOOL_BASE::doInteractiveItemPlacement ( const std::string &  aTool,
INTERACTIVE_PLACER_BASE aPlacer,
const wxString &  aCommitMessage,
int  aOptions = IPO_ROTATE | IPO_FLIP | IPO_REPEAT 
)
protectedinherited

Helper function for performing a common interactive idiom: wait for a left click, place an item there (perhaps with a dialog or other user interaction), then have it move with the mouse and respond to rotate/flip, etc.

More complex interactive processes are not supported here, you should implement a customised event loop for those.

Parameters
aItemCreatorthe callable that will attempt to create the item
aCommitMessagethe message used on a successful commit

Definition at line 37 of file pcb_tool_base.cpp.

40 {
41  using namespace std::placeholders;
42  std::unique_ptr<BOARD_ITEM> newItem;
43 
44  frame()->PushTool( aTool );
45  Activate();
46 
47  BOARD_COMMIT commit( frame() );
48 
50 
51  // do not capture or auto-pan until we start placing an item
52  controls()->ShowCursor( true );
53  controls()->SetSnapping( true );
54 
55  // Add a VIEW_GROUP that serves as a preview for the new item
56  PCBNEW_SELECTION preview;
57  view()->Add( &preview );
58 
59  aPlacer->m_board = board();
60  aPlacer->m_frame = frame();
61  aPlacer->m_modifiers = 0;
62 
63  auto makeNewItem = [&] ( VECTOR2I aPosition )
64  {
65  if( frame()->GetModel() )
66  newItem = aPlacer->CreateItem();
67 
68  if( newItem )
69  {
70  newItem->SetPosition( (wxPoint) aPosition );
71  preview.Add( newItem.get() );
72 
73  if( newItem->Type() == PCB_MODULE_T )
74  {
75  auto module = dyn_cast<MODULE*>( newItem.get() );
76 
77  // modules have more drawable parts
78  module->RunOnChildren( std::bind( &KIGFX::VIEW_GROUP::Add, &preview, _1 ) );
79  }
80  }
81  };
82 
83  if( aOptions & IPO_SINGLE_CLICK )
84  makeNewItem( controls()->GetCursorPosition() );
85 
86  // Main loop: keep receiving events
87  while( TOOL_EVENT* evt = Wait() )
88  {
89  VECTOR2I cursorPos = controls()->GetCursorPosition();
90  aPlacer->m_modifiers = evt->Modifier();
91 
92  auto cleanup = [&] ()
93  {
94  newItem = nullptr;
95  preview.Clear();
96  view()->Update( &preview );
97  controls()->SetAutoPan( false );
98  controls()->CaptureCursor( false );
99  controls()->ShowCursor( true );
100  };
101 
102  if( evt->IsCancelInteractive() )
103  {
104  if( aOptions & IPO_SINGLE_CLICK )
105  {
106  cleanup();
107  frame()->PopTool( aTool );
108  break;
109  }
110  else if( newItem )
111  cleanup();
112  else
113  {
114  frame()->PopTool( aTool );
115  break;
116  }
117  }
118  else if( evt->IsActivate() )
119  {
120  if( newItem )
121  cleanup();
122 
123  if( evt->IsPointEditor() )
124  {
125  // don't exit (the point editor runs in the background)
126  }
127  else if( evt->IsMoveTool() )
128  {
129  // leave ourselves on the stack so we come back after the move
130  break;
131  }
132  else
133  {
134  frame()->PopTool( aTool );
135  break;
136  }
137  }
138  else if( evt->IsClick( BUT_LEFT ) )
139  {
140  if( !newItem )
141  {
142  // create the item if possible
143  makeNewItem( cursorPos );
144 
145  // no item created, so wait for another click
146  if( !newItem )
147  continue;
148 
149  controls()->CaptureCursor( true );
150  controls()->SetAutoPan( true );
151  }
152  else
153  {
154  auto oldFlags = newItem->GetFlags();
155  newItem->ClearFlags();
156 
157  if( !aPlacer->PlaceItem( newItem.get(), commit ) )
158  {
159  newItem->SetFlags( oldFlags );
160  continue;
161  }
162 
163  preview.Clear();
164  newItem.release();
165  commit.Push( aCommitMessage );
166 
167  controls()->CaptureCursor( false );
168  controls()->SetAutoPan( false );
169  controls()->ShowCursor( true );
170 
171  if( !( aOptions & IPO_REPEAT ) )
172  break;
173 
174  if( aOptions & IPO_SINGLE_CLICK )
175  makeNewItem( controls()->GetCursorPosition() );
176  }
177  }
178  else if( evt->IsClick( BUT_RIGHT ) )
179  {
181  }
182  else if( newItem && evt->Category() == TC_COMMAND )
183  {
184  /*
185  * Handle any events that can affect the item as we move it around
186  */
187  if( TOOL_EVT_UTILS::IsRotateToolEvt( *evt ) && ( aOptions & IPO_ROTATE ) )
188  {
189  const int rotationAngle = TOOL_EVT_UTILS::GetEventRotationAngle( *frame(), *evt );
190  newItem->Rotate( newItem->GetPosition(), rotationAngle );
191  view()->Update( &preview );
192  }
193  else if( evt->IsAction( &PCB_ACTIONS::flip ) && ( aOptions & IPO_FLIP ) )
194  {
195  newItem->Flip( newItem->GetPosition(), frame()->Settings().m_FlipLeftRight );
196  view()->Update( &preview );
197  }
198  else if( evt->IsAction( &PCB_ACTIONS::viaSizeInc )
199  || evt->IsAction( &PCB_ACTIONS::viaSizeDec ) )
200  {
201  // Refresh preview after event runs
203  }
204  else if( evt->IsAction( &ACTIONS::refreshPreview ) )
205  {
206  preview.Clear();
207  newItem.release();
208 
209  makeNewItem( controls()->GetCursorPosition() );
210  view()->Update( &preview );
211  }
212  }
213 
214  else if( newItem && evt->IsMotion() )
215  {
216  // track the cursor
217  newItem->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
218  aPlacer->SnapItem( newItem.get() );
219 
220  // Show a preview of the item
221  view()->Update( &preview );
222  }
223 
224  else
225  evt->SetPassEvent();
226  }
227 
228  view()->Remove( &preview );
229 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
virtual void ShowCursor(bool aEnabled)
Function ShowCursor() Enables or disables display of cursor.
virtual void PushTool(const std::string &actionName)
NB: the definition of "tool" is different at the user level.
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
virtual void Clear() override
Function Clear() Removes all the stored items from the group.
Definition: selection.h:94
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
TOOL_EVENT * Wait(const TOOL_EVENT_LIST &aEventList=TOOL_EVENT(TC_ANY, TA_ANY))
Function Wait()
virtual bool PlaceItem(BOARD_ITEM *aItem, BOARD_COMMIT &aCommit)
BOARD * board() const
virtual void Update(VIEW_ITEM *aItem, int aUpdateFlags) override
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: pcb_view.cpp:91
static TOOL_ACTION viaSizeInc
Definition: pcb_actions.h:284
virtual std::unique_ptr< BOARD_ITEM > CreateItem()=0
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
virtual void SetSnapping(bool aEnabled)
Function SetSnapping() Enables/disables snapping cursor to grid.
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
bool IsRotateToolEvt(const TOOL_EVENT &aEvt)
Function isRotateToolEvt()
virtual void Remove(VIEW_ITEM *aItem) override
Function Remove() Removes a VIEW_ITEM from the view.
Definition: pcb_view.cpp:74
virtual void Add(EDA_ITEM *aItem)
Definition: selection.h:75
TOOL_MANAGER * GetManager() const
Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool.
Definition: tool_base.h:142
PCB_BASE_EDIT_FRAME * frame() const
virtual void SnapItem(BOARD_ITEM *aItem)
class MODULE, a footprint
Definition: typeinfo.h:89
const PCBNEW_SELECTION & selection() const
virtual void CaptureCursor(bool aEnabled)
Function CaptureCursor() Forces the cursor to stay within the drawing panel area.
TOOL_EVENT.
Definition: tool_event.h:171
KIGFX::PCB_VIEW * view() const
virtual void Add(VIEW_ITEM *aItem)
Function Add() Adds an item to the group.
Definition: view_group.cpp:55
virtual void SetAutoPan(bool aEnabled)
Function SetAutoPan Turns on/off auto panning (this feature is used when there is a tool active (eg.
static TOOL_ACTION flip
Flipping of selected objects.
Definition: pcb_actions.h:111
KIGFX::VIEW_CONTROLS * controls() const
MODULE * module() const
PCBNEW_SETTINGS & Settings()
virtual void PopTool(const std::string &actionName)
void Activate()
Function Activate() Runs the tool.
virtual BOARD_ITEM_CONTAINER * GetModel() const =0
Function GetModel()
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1) override
Function Add() Adds a VIEW_ITEM to the view.
Definition: pcb_view.cpp:58
PCB_BASE_EDIT_FRAME * m_frame
Definition: pcb_tool_base.h:62
int GetEventRotationAngle(const PCB_BASE_EDIT_FRAME &aFrame, const TOOL_EVENT &aEvt)
Function getEventRotationAngle()
void ShowContextMenu(SELECTION &aSelection)
Function ShowContextMenu.
Definition: tool_menu.cpp:59
static TOOL_ACTION viaSizeDec
Definition: pcb_actions.h:285
static TOOL_ACTION refreshPreview
Definition: actions.h:101
VECTOR2D GetCursorPosition() const
Returns the current cursor position in world coordinates.

References TOOL_INTERACTIVE::Activate(), KIGFX::PCB_VIEW::Add(), KIGFX::VIEW_GROUP::Add(), SELECTION::Add(), PCB_TOOL_BASE::board(), BUT_LEFT, BUT_RIGHT, KIGFX::VIEW_CONTROLS::CaptureCursor(), SELECTION::Clear(), PCB_TOOL_BASE::controls(), INTERACTIVE_PLACER_BASE::CreateItem(), PCB_ACTIONS::flip, PCB_TOOL_BASE::frame(), KIGFX::VIEW_CONTROLS::GetCursorPosition(), TOOL_EVT_UTILS::GetEventRotationAngle(), TOOL_BASE::GetManager(), PCB_BASE_EDIT_FRAME::GetModel(), PCB_TOOL_BASE::IPO_FLIP, PCB_TOOL_BASE::IPO_REPEAT, PCB_TOOL_BASE::IPO_ROTATE, PCB_TOOL_BASE::IPO_SINGLE_CLICK, TOOL_EVT_UTILS::IsRotateToolEvt(), INTERACTIVE_PLACER_BASE::m_board, PCBNEW_SETTINGS::m_FlipLeftRight, INTERACTIVE_PLACER_BASE::m_frame, TOOL_INTERACTIVE::m_menu, INTERACTIVE_PLACER_BASE::m_modifiers, TOOL_BASE::m_toolMgr, PCB_TOOL_BASE::module(), PCB_MODULE_T, INTERACTIVE_PLACER_BASE::PlaceItem(), EDA_BASE_FRAME::PopTool(), BOARD_COMMIT::Push(), EDA_BASE_FRAME::PushTool(), ACTIONS::refreshPreview, KIGFX::PCB_VIEW::Remove(), TOOL_MANAGER::RunAction(), MODULE::RunOnChildren(), PCB_TOOL_BASE::selection(), PCB_ACTIONS::selectionClear, KIGFX::VIEW_CONTROLS::SetAutoPan(), KIGFX::VIEW_CONTROLS::SetSnapping(), PCB_BASE_FRAME::Settings(), TOOL_MENU::ShowContextMenu(), KIGFX::VIEW_CONTROLS::ShowCursor(), INTERACTIVE_PLACER_BASE::SnapItem(), TC_COMMAND, KIGFX::PCB_VIEW::Update(), PCB_ACTIONS::viaSizeDec, PCB_ACTIONS::viaSizeInc, PCB_TOOL_BASE::view(), TOOL_INTERACTIVE::Wait(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by MICROWAVE_TOOL::addMicrowaveFootprint(), DRAWING_TOOL::DrawVia(), and MODULE_EDITOR_TOOLS::PlacePad().

◆ doNetClass()

bool DRC::doNetClass ( const std::shared_ptr< NETCLASS > &  aNetClass,
wxString &  msg 
)
private

Definition at line 519 of file pcbnew/drc/drc.cpp.

520 {
521  bool ret = true;
522 
524 
525 #define FmtVal( x ) GetChars( StringFromValue( m_pcbEditorFrame->GetUserUnits(), x ) )
526 
527 #if 0 // set to 1 when (if...) BOARD_DESIGN_SETTINGS has a m_MinClearance value
528  if( nc->GetClearance() < g.m_MinClearance )
529  {
530  msg.Printf( _( "NETCLASS: \"%s\" has Clearance:%s which is less than global:%s" ),
531  GetChars( nc->GetName() ),
532  FmtVal( nc->GetClearance() ),
533  FmtVal( g.m_TrackClearance )
534  );
535 
537  ret = false;
538  }
539 #endif
540 
541  if( nc->GetTrackWidth() < g.m_TrackMinWidth )
542  {
543  msg.Printf( _( "NETCLASS: \"%s\" has TrackWidth:%s which is less than global:%s" ),
544  GetChars( nc->GetName() ),
545  FmtVal( nc->GetTrackWidth() ),
547  );
548 
550  ret = false;
551  }
552 
553  if( nc->GetViaDiameter() < g.m_ViasMinSize )
554  {
555  msg.Printf( _( "NETCLASS: \"%s\" has Via Dia:%s which is less than global:%s" ),
556  GetChars( nc->GetName() ),
557  FmtVal( nc->GetViaDiameter() ),
558  FmtVal( g.m_ViasMinSize )
559  );
560 
562  ret = false;
563  }
564 
565  if( nc->GetViaDrill() < g.m_ViasMinDrill )
566  {
567  msg.Printf( _( "NETCLASS: \"%s\" has Via Drill:%s which is less than global:%s" ),
568  GetChars( nc->GetName() ),
569  FmtVal( nc->GetViaDrill() ),
571  );
572 
574  ret = false;
575  }
576 
577  if( nc->GetuViaDiameter() < g.m_MicroViasMinSize )
578  {
579  msg.Printf( _( "NETCLASS: \"%s\" has uVia Dia:%s which is less than global:%s" ),
580  GetChars( nc->GetName() ),
581  FmtVal( nc->GetuViaDiameter() ),
582  FmtVal( g.m_MicroViasMinSize ) );
583 
585  ret = false;
586  }
587 
588  if( nc->GetuViaDrill() < g.m_MicroViasMinDrill )
589  {
590  msg.Printf( _( "NETCLASS: \"%s\" has uVia Drill:%s which is less than global:%s" ),
591  GetChars( nc->GetName() ),
592  FmtVal( nc->GetuViaDrill() ),
594 
596  ret = false;
597  }
598 
599  return ret;
600 }
#define FmtVal(x)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
netclass has Clearance < board.m_designSettings->m_TrackClearance
Definition: drc.h:68
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
netclass has TrackWidth < board.m_designSettings->m_TrackMinWidth
Definition: drc.h:67
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:101
netclass has ViaDrillSize < board.m_designSettings->m_ViasMinDrill
Definition: drc.h:70
#define _(s)
Definition: 3d_actions.cpp:33
netclass has ViaSize < board.m_designSettings->m_MicroViasMinDrill
Definition: drc.h:72
netclass has ViaSize < board.m_designSettings->m_ViasMinSize
Definition: drc.h:69
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
netclass has ViaSize < board.m_designSettings->m_MicroViasMinSize
Definition: drc.h:71

References _, addMarkerToPcb(), DRCE_NETCLASS_CLEARANCE, DRCE_NETCLASS_TRACKWIDTH, DRCE_NETCLASS_uVIADRILLSIZE, DRCE_NETCLASS_uVIASIZE, DRCE_NETCLASS_VIADRILLSIZE, DRCE_NETCLASS_VIASIZE, FmtVal, GetChars(), BOARD::GetDesignSettings(), 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().

◆ doOverlappingCourtyardsDrc()

void DRC::doOverlappingCourtyardsDrc ( )
private

Test for footprint courtyard overlaps.

Definition at line 1327 of file pcbnew/drc/drc.cpp.

1328 {
1329  DRC_COURTYARD_OVERLAP drc_overlap( [&]( MARKER_PCB* aMarker ) { addMarkerToPcb( aMarker ); } );
1330 
1331  drc_overlap.RunDRC( userUnits(), *m_pcb );
1332 }
EDA_UNITS userUnits() const
Definition: drc.h:196
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
A class that provides the courtyard-based DRC checks.
bool RunDRC(EDA_UNITS aUnits, BOARD &aBoard) const override
Runs this provider against the given PCB with configured options (if any).

References addMarkerToPcb(), m_pcb, DRC_COURTYARD_OVERLAP::RunDRC(), and userUnits().

Referenced by RunTests().

◆ doPadToPadsDrc()

bool DRC::doPadToPadsDrc ( D_PAD aRefPad,
D_PAD **  aStart,
D_PAD **  aEnd,
int  x_limit 
)
private

Test the clearance between aRefPad and other pads.

The pad list must be sorted by x coordinate.

Parameters
aRefPadis the pad to test
aStartis the first pad of the list to test against aRefPad
aEndis the end of the list and is not included
x_limitis used to stop the test (i.e. when the current pad pos X in list exceeds this limit, because the list is sorted by X coordinate)

Definition at line 1192 of file pcbnew/drc/drc.cpp.

1193 {
1194  const static LSET all_cu = LSET::AllCuMask();
1195 
1196  LSET layerMask = aRefPad->GetLayerSet() & all_cu;
1197 
1198  /* used to test DRC pad to holes: this dummy pad has the size and shape of the hole
1199  * to test pad to pad hole DRC, using the pad to pad DRC test function.
1200  * Therefore, this dummy pad is a circle or an oval.
1201  * A pad must have a parent because some functions expect a non null parent
1202  * to find the parent board, and some other data
1203  */
1204  MODULE dummymodule( m_pcb ); // Creates a dummy parent
1205  D_PAD dummypad( &dummymodule );
1206 
1207  // Ensure the hole is on all copper layers
1208  dummypad.SetLayerSet( all_cu | dummypad.GetLayerSet() );
1209 
1210  // Use the minimal local clearance value for the dummy pad.
1211  // The clearance of the active pad will be used as minimum distance to a hole
1212  // (a value = 0 means use netclass value)
1213  dummypad.SetLocalClearance( 1 );
1214 
1215  for( D_PAD** pad_list = aStart; pad_list<aEnd; ++pad_list )
1216  {
1217  D_PAD* pad = *pad_list;
1218 
1219  if( pad == aRefPad )
1220  continue;
1221 
1222  // We can stop the test when pad->GetPosition().x > x_limit
1223  // because the list is sorted by X values
1224  if( pad->GetPosition().x > x_limit )
1225  break;
1226 
1227  // No problem if pads which are on copper layers are on different copper layers,
1228  // (pads can be only on a technical layer, to build complex pads)
1229  // but their hole (if any ) can create DRC error because they are on all
1230  // copper layers, so we test them
1231  if( ( pad->GetLayerSet() & layerMask ) == 0 &&
1232  ( pad->GetLayerSet() & all_cu ) != 0 &&
1233  ( aRefPad->GetLayerSet() & all_cu ) != 0 )
1234  {
1235  // if holes are in the same location and have the same size and shape,
1236  // this can be accepted
1237  if( pad->GetPosition() == aRefPad->GetPosition()
1238  && pad->GetDrillSize() == aRefPad->GetDrillSize()
1239  && pad->GetDrillShape() == aRefPad->GetDrillShape() )
1240  {
1241  if( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
1242  continue;
1243 
1244  // for oval holes: must also have the same orientation
1245  if( pad->GetOrientation() == aRefPad->GetOrientation() )
1246  continue;
1247  }
1248 
1249  /* Here, we must test clearance between holes and pads
1250  * dummy pad size and shape is adjusted to pad drill size and shape
1251  */
1252  if( pad->GetDrillSize().x )
1253  {
1254  // pad under testing has a hole, test this hole against pad reference
1255  dummypad.SetPosition( pad->GetPosition() );
1256  dummypad.SetSize( pad->GetDrillSize() );
1257  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1259  dummypad.SetOrientation( pad->GetOrientation() );
1260 
1261  if( !checkClearancePadToPad( aRefPad, &dummypad ) )
1262  {
1263  // here we have a drc error on pad!
1265  pad->GetPosition(), pad, aRefPad ) );
1266  return false;
1267  }
1268  }
1269 
1270  if( aRefPad->GetDrillSize().x ) // pad reference has a hole
1271  {
1272  dummypad.SetPosition( aRefPad->GetPosition() );
1273  dummypad.SetSize( aRefPad->GetDrillSize() );
1274  dummypad.SetShape( aRefPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
1276  dummypad.SetOrientation( aRefPad->GetOrientation() );
1277 
1278  if( !checkClearancePadToPad( pad, &dummypad ) )
1279  {
1280  // here we have a drc error on aRefPad!
1282  aRefPad->GetPosition(), aRefPad, pad ) );
1283  return false;
1284  }
1285  }
1286 
1287  continue;
1288  }
1289 
1290  // The pad must be in a net (i.e pt_pad->GetNet() != 0 ),
1291  // But no problem if pads have the same netcode (same net)
1292  if( pad->GetNetCode() && ( aRefPad->GetNetCode() == pad->GetNetCode() ) )
1293  continue;
1294 
1295  // if pads are from the same footprint
1296  if( pad->GetParent() == aRefPad->GetParent() )
1297  {
1298  // and have the same pad number ( equivalent pads )
1299 
1300  // one can argue that this 2nd test is not necessary, that any
1301  // two pads from a single module are acceptable. This 2nd test
1302  // should eventually be a configuration option.
1303  if( pad->PadNameEqual( aRefPad ) )
1304  continue;
1305  }
1306 
1307  // if either pad has no drill and is only on technical layers, not a clearance violation
1308  if( ( ( pad->GetLayerSet() & layerMask ) == 0 && !pad->GetDrillSize().x ) ||
1309  ( ( aRefPad->GetLayerSet() & layerMask ) == 0 && !aRefPad->GetDrillSize().x ) )
1310  {
1311  continue;
1312  }
1313 
1314  if( !checkClearancePadToPad( aRefPad, pad ) )
1315  {
1316  // here we have a drc error!
1318  aRefPad->GetPosition(), aRefPad, pad ) );
1319  return false;
1320  }
1321  }
1322 
1323  return true;
1324 }
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:686
int GetNetCode() const
Function GetNetCode.
bool PadNameEqual(const D_PAD *other) const
Definition: class_pad.h:228
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:240
EDA_UNITS userUnits() const
Definition: drc.h:196
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
LSET is a set of PCB_LAYER_IDs.
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:432
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:446
MODULE * GetParent() const
Definition: class_pad.h:167
bool checkClearancePadToPad(D_PAD *aRefPad, D_PAD *aPad)
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:426
const wxSize & GetDrillSize() const
Definition: class_pad.h:306
hole too close to pad
Definition: drc.h:60
const wxPoint GetPosition() const override
Definition: class_pad.h:241
pad too close to pad
Definition: drc.h:54

References addMarkerToPcb(), LSET::AllCuMask(), checkClearancePadToPad(), DRCE_HOLE_NEAR_PAD, DRCE_PAD_NEAR_PAD1, D_PAD::GetDrillShape(), D_PAD::GetDrillSize(), D_PAD::GetLayerSet(), BOARD_CONNECTED_ITEM::GetNetCode(), D_PAD::GetOrientation(), D_PAD::GetParent(), D_PAD::GetPosition(), m_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(), userUnits(), and wxPoint::x.

Referenced by testPad2Pad().

◆ doTrackDrc()

void DRC::doTrackDrc ( TRACK aRefSeg,
TRACKS::iterator  aStartIt,
TRACKS::iterator  aEndIt,
bool  aTestZones 
)
private

Test the current segment.

Parameters
aRefSegThe segment to test
aStartItthe iterator to the first track to test
aEndItthe marker for the iterator end
aTestZonestrue if should do copper zones test. This can be very time consumming
Returns
bool - true if no problems, else false and m_currentMarker is filled in with the problem information.

Definition at line 110 of file drc_clearance_test_functions.cpp.

112 {
113  TRACK* track;
114  wxPoint delta; // length on X and Y axis of segments
115  wxPoint shape_pos;
116 
117  NETCLASSPTR netclass = aRefSeg->GetNetClass();
119 
120  // In order to make some calculations more easier or faster, pads and tracks
121  // coordinates will be made relative to the reference segment origin
122  wxPoint origin = aRefSeg->GetStart();
123 
124  m_segmEnd = delta = aRefSeg->GetEnd() - origin;
125  m_segmAngle = 0;
126 
127  LSET layerMask = aRefSeg->GetLayerSet();
128  int net_code_ref = aRefSeg->GetNetCode();
129  int ref_seg_clearance = netclass->GetClearance();
130  int ref_seg_width = aRefSeg->GetWidth();
131 
132 
133  /******************************************/
134  /* Phase 0 : via DRC tests : */
135  /******************************************/
136 
137  if( aRefSeg->Type() == PCB_VIA_T )
138  {
139  VIA *refvia = static_cast<VIA*>( aRefSeg );
140 
141  // test if the via size is smaller than minimum
142  if( refvia->GetViaType() == VIATYPE::MICROVIA )
143  {
144  if( refvia->GetWidth() < dsnSettings.m_MicroViasMinSize )
145  {
147  refvia->GetPosition(), refvia ) );
148  }
149 
150  if( refvia->GetDrillValue() < dsnSettings.m_MicroViasMinDrill )
151  {
153  refvia->GetPosition(), refvia ) );
154  }
155  }
156  else
157  {
158  if( refvia->GetWidth() < dsnSettings.m_ViasMinSize )
159  {
161  refvia->GetPosition(), refvia ) );
162  }
163 
164  if( refvia->GetDrillValue() < dsnSettings.m_ViasMinDrill )
165  {
167  refvia->GetPosition(), refvia ) );
168  }
169  }
170 
171  // test if via's hole is bigger than its diameter
172  // This test is necessary since the via hole size and width can be modified
173  // and a default via hole can be bigger than some vias sizes
174  if( refvia->GetDrillValue() > refvia->GetWidth() )
175  {
177  refvia->GetPosition(), refvia ) );
178  }
179 
180  // test if the type of via is allowed due to design rules
181  if( refvia->GetViaType() == VIATYPE::MICROVIA && !dsnSettings.m_MicroViasAllowed )
182  {
184  refvia->GetPosition(), refvia ) );
185  }
186 
187  // test if the type of via is allowed due to design rules
188  if( refvia->GetViaType() == VIATYPE::BLIND_BURIED && !dsnSettings.m_BlindBuriedViaAllowed )
189  {
191  refvia->GetPosition(), refvia ) );
192  }
193 
194  // For microvias: test if they are blind vias and only between 2 layers
195  // because they are used for very small drill size and are drill by laser
196  // and **only one layer** can be drilled
197  if( refvia->GetViaType() == VIATYPE::MICROVIA )
198  {
199  PCB_LAYER_ID layer1, layer2;
200  bool err = true;
201 
202  refvia->LayerPair( &layer1, &layer2 );
203 
204  if( layer1 > layer2 )
205  std::swap( layer1, layer2 );
206 
207  if( layer2 == B_Cu && layer1 == dsnSettings.GetCopperLayerCount() - 2 )
208  err = false;
209  else if( layer1 == F_Cu && layer2 == In1_Cu )
210  err = false;
211 
212  if( err )
213  {
215  refvia->GetPosition(), refvia ) );
216  }
217  }
218 
219  }
220  else // This is a track segment
221  {
222  if( ref_seg_width < dsnSettings.m_TrackMinWidth )
223  {
224  wxPoint refsegMiddle = ( aRefSeg->GetStart() + aRefSeg->GetEnd() ) / 2;
225 
227  refsegMiddle, aRefSeg ) );
228  }
229  }
230 
231  // for a non horizontal or vertical segment Compute the segment angle
232  // in tenths of degrees and its length
233  if( delta.x || delta.y )
234  {
235  // Compute the segment angle in 0,1 degrees
236  m_segmAngle = ArcTangente( delta.y, delta.x );
237 
238  // Compute the segment length: we build an equivalent rotated segment,
239  // this segment is horizontal, therefore dx = length
240  RotatePoint( &delta, m_segmAngle ); // delta.x = length, delta.y = 0
241  }
242 
243  m_segmLength = delta.x;
244 
245  /******************************************/
246  /* Phase 1 : test DRC track to pads : */
247  /******************************************/
248 
249  /* Use a dummy pad to test DRC tracks versus holes, for pads not on all copper layers
250  * but having a hole
251  * This dummy pad has the size and shape of the hole
252  * to test tracks to pad hole DRC, using checkClearanceSegmToPad test function.
253  * Therefore, this dummy pad is a circle or an oval.
254  * A pad must have a parent because some functions expect a non null parent
255  * to find the parent board, and some other data
256  */
257  MODULE dummymodule( m_pcb ); // Creates a dummy parent
258  D_PAD dummypad( &dummymodule );
259 
260  dummypad.SetLayerSet( LSET::AllCuMask() ); // Ensure the hole is on all layers
261 
262  // Compute the min distance to pads
263  for( MODULE* mod : m_pcb->Modules() )
264  {
265  for( D_PAD* pad : mod->Pads() )
266  {
267  SEG padSeg( pad->GetPosition(), pad->GetPosition() );
268 
269  // No problem if pads are on another layer, but if a drill hole exists (a pad on
270  // a single layer can have a hole!) we must test the hole
271  if( !( pad->GetLayerSet() & layerMask ).any() )
272  {
273  // We must test the pad hole. In order to use checkClearanceSegmToPad(), a
274  // pseudo pad is used, with a shape and a size like the hole
275  if( pad->GetDrillSize().x == 0 )
276  continue;
277 
278  dummypad.SetSize( pad->GetDrillSize() );
279  dummypad.SetPosition( pad->GetPosition() );
280  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
283  dummypad.SetOrientation( pad->GetOrientation() );
284 
285  m_padToTestPos = dummypad.GetPosition() - origin;
286 
287  if( !checkClearanceSegmToPad( &dummypad, ref_seg_width, ref_seg_clearance ) )
288  {
290  getLocation( aRefSeg, pad, padSeg ),
291  aRefSeg, pad ) );
292 
294  return;
295  }
296 
297  continue;
298  }
299 
300  // The pad must be in a net (i.e pt_pad->GetNet() != 0 )
301  // but no problem if the pad netcode is the current netcode (same net)
302  if( pad->GetNetCode() // the pad must be connected
303  && net_code_ref == pad->GetNetCode() ) // the pad net is the same as current net -> Ok
304  continue;
305 
306  // DRC for the pad
307  shape_pos = pad->ShapePos();
308  m_padToTestPos = shape_pos - origin;
309  int segToPadClearance = std::max( ref_seg_clearance, pad->GetClearance() );
310 
311  if( !checkClearanceSegmToPad( pad, ref_seg_width, segToPadClearance ) )
312  {
314  getLocation( aRefSeg, pad, padSeg ),
315  aRefSeg, pad ) );
316 
318  return;
319  }
320  }
321  }
322 
323  /***********************************************/
324  /* Phase 2: test DRC with other track segments */
325  /***********************************************/
326 
327  // At this point the reference segment is the X axis
328 
329  // Test the reference segment with other track segments
330  wxPoint segStartPoint;
331  wxPoint segEndPoint;
332 
333  for( auto it = aStartIt; it != aEndIt; it++ )
334  {
335  track = *it;
336  // No problem if segments have the same net code:
337  if( net_code_ref == track->GetNetCode() )
338  continue;
339 
340  // No problem if segment are on different layers :
341  if( !( layerMask & track->GetLayerSet() ).any() )
342  continue;
343 
344  // the minimum distance = clearance plus half the reference track
345  // width plus half the other track's width
346  int w_dist = std::max( ref_seg_clearance, track->GetClearance() );
347  w_dist += ( ref_seg_width + track->GetWidth() ) / 2;
348 
349  // Due to many double to int conversions during calculations, which
350  // create rounding issues,
351  // the exact clearance margin cannot be really known.
352  // To avoid false bad DRC detection due to these rounding issues,
353  // slightly decrease the w_dist (remove one nanometer is enough !)
354  w_dist -= 1;
355 
356  // If the reference segment is a via, we test it here
357  if( aRefSeg->Type() == PCB_VIA_T )
358  {
359  delta = track->GetEnd() - track->GetStart();
360  segStartPoint = aRefSeg->GetStart() - track->GetStart();
361 
362  if( track->Type() == PCB_VIA_T )
363  {
364  // Test distance between two vias, i.e. two circles, trivial case
365  if( EuclideanNorm( segStartPoint ) < w_dist )
366  {
368  aRefSeg->GetPosition(), aRefSeg, track ) );
369 
371  return;
372  }
373  }
374  else // test via to segment
375  {
376  // Compute l'angle du segment a tester;
377  double angle = ArcTangente( delta.y, delta.x );
378 
379  // Compute new coordinates ( the segment become horizontal)
380  RotatePoint( &delta, angle );
381  RotatePoint( &segStartPoint, angle );
382 
383  if( !checkMarginToCircle( segStartPoint, w_dist, delta.x ) )
384  {
386  aRefSeg->GetPosition(), aRefSeg, track ) );
387 
389  return;
390  }
391  }
392 
393  continue;
394  }
395 
396  /* We compute segStartPoint, segEndPoint = starting and ending point coordinates for
397  * the segment to test in the new axis : the new X axis is the
398  * reference segment. We must translate and rotate the segment to test
399  */
400  segStartPoint = track->GetStart() - origin;
401  segEndPoint = track->GetEnd() - origin;
402  RotatePoint( &segStartPoint, m_segmAngle );
403  RotatePoint( &segEndPoint, m_segmAngle );
404 
405  SEG seg( segStartPoint, segEndPoint );
406 
407  if( track->Type() == PCB_VIA_T )
408  {
409  if( checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
410  continue;
411 
413  getLocation( aRefSeg, track, seg ), aRefSeg, track ) );
414 
416  return;
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 another 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 ) )
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  {
442  getLocation( aRefSeg, track, seg ),
443  aRefSeg, track ) );
444 
446  return;
447  }
448 
449  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
450  {
452  getLocation( aRefSeg, track, seg ),
453  aRefSeg, track ) );
454 
456  return;
457  }
458  }
459 
460  if( segEndPoint.x > ( -w_dist ) && segEndPoint.x < ( m_segmLength + w_dist ) )
461  {
462  // the end point is inside the reference range
463  // .....X
464  // O--REF--+
465  // Fine test : we consider the rounded shape of the ends
466  if( segEndPoint.x >= 0 && segEndPoint.x <= m_segmLength )
467  {
469  getLocation( aRefSeg, track, seg ),
470  aRefSeg, track ) );
471 
473  return;
474  }
475 
476  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
477  {
479  getLocation( aRefSeg, track, seg ),
480  aRefSeg, track ) );
481 
483  return;
484  }
485  }
486 
487  if( segStartPoint.x <= 0 && segEndPoint.x >= 0 )
488  {
489  // the segment straddles the reference range (this actually only
490  // checks if it straddles the origin, because the other cases where already
491  // handled)
492  // X.............X
493  // O--REF--+
495  getLocation( aRefSeg, track, seg ),
496  aRefSeg, track ) );
497 
499  return;
500  }
501  }
502  else if( segStartPoint.x == segEndPoint.x ) // perpendicular segments
503  {
504  if( segStartPoint.x <= -w_dist || segStartPoint.x >= m_segmLength + w_dist )
505  continue;
506 
507  // Test if segments are crossing
508  if( segStartPoint.y > segEndPoint.y )
509  std::swap( segStartPoint.y, segEndPoint.y );
510 
511  if( ( segStartPoint.y < 0 ) && ( segEndPoint.y > 0 ) )
512  {
514  wxPoint( track->GetStart().x, aRefSeg->GetStart().y ),
515  aRefSeg, track ) );
516 
518  return;
519  }
520 
521  // At this point the drc error is due to an end near a reference segm end
522  if( !checkMarginToCircle( segStartPoint, w_dist, m_segmLength ) )
523  {
525  getLocation( aRefSeg, track, seg ),
526  aRefSeg, track ) );
527 
529  return;
530  }
531  if( !checkMarginToCircle( segEndPoint, w_dist, m_segmLength ) )
532  {
534  getLocation( aRefSeg, track, seg ),
535  aRefSeg, track ) );
536 
538  return;
539  }
540  }
541  else // segments quelconques entre eux
542  {
543  // calcul de la "surface de securite du segment de reference
544  // First rought 'and fast) test : the track segment is like a rectangle
545 
546  m_xcliplo = m_ycliplo = -w_dist;
547  m_xcliphi = m_segmLength + w_dist;
548  m_ycliphi = w_dist;
549 
550  // A fine test is needed because a serment is not exactly a
551  // rectangle, it has rounded ends
552  if( !checkLine( segStartPoint, segEndPoint ) )
553  {
554  /* 2eme passe : the track has rounded ends.
555  * we must a fine test for each rounded end and the
556  * rectangular zone
557  */
558 
559  m_xcliplo = 0;
561 
562  if( !checkLine( segStartPoint, segEndPoint ) )
563  {
564  wxPoint failurePoint;
565 
566  if( SegmentIntersectsSegment( aRefSeg->GetStart(), aRefSeg->GetEnd(),
567  track->GetStart(), track->GetEnd(),
568  &failurePoint ) )
569  {
571  failurePoint, aRefSeg, track ) );
572  }
573  else
574  {
576  getLocation( aRefSeg, track, seg ),
577  aRefSeg, track ) );
578  }
579 
581  return;
582  }
583  else // The drc error is due to the starting or the ending point of the reference segment
584  {
585  // Test the starting and the ending point
586  segStartPoint = track->GetStart();
587  segEndPoint = track->GetEnd();
588  delta = segEndPoint - segStartPoint;
589 
590  // Compute the segment orientation (angle) en 0,1 degre
591  double angle = ArcTangente( delta.y, delta.x );
592 
593  // Compute the segment length: delta.x = length after rotation
594  RotatePoint( &delta, angle );
595 
596  /* Comute the reference segment coordinates relatives to a
597  * X axis = current tested segment
598  */
599  wxPoint relStartPos = aRefSeg->GetStart() - segStartPoint;
600  wxPoint relEndPos = aRefSeg->GetEnd() - segStartPoint;
601 
602  RotatePoint( &relStartPos, angle );
603  RotatePoint( &relEndPos, angle );
604 
605  if( !checkMarginToCircle( relStartPos, w_dist, delta.x ) )
606  {
608  getLocation( aRefSeg, track, seg ),
609  aRefSeg, track ) );
610 
612  return;
613  }
614 
615  if( !checkMarginToCircle( relEndPos, w_dist, delta.x ) )
616  {
618  getLocation( aRefSeg, track, seg ),
619  aRefSeg, track ) );
620 
622  return;
623  }
624  }
625  }
626  }
627  }
628 
629  /***************************************/
630  /* Phase 3: test DRC with copper zones */
631  /***************************************/
632  // Can be *very* time consumming.
633  if( aTestZones )
634  {
635  SEG refSeg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
636 
637  for( ZONE_CONTAINER* zone : m_pcb->Zones() )
638  {
639  if( zone->GetFilledPolysList().IsEmpty() || zone->GetIsKeepout() )
640  continue;
641 
642  if( !( layerMask & zone->GetLayerSet() ).any() )
643  continue;
644 
645  if( zone->GetNetCode() && zone->GetNetCode() == net_code_ref )
646  continue;
647 
648  int clearance = std::max( ref_seg_clearance, zone->GetClearance() );
649  SHAPE_POLY_SET* outline = const_cast<SHAPE_POLY_SET*>( &zone->GetFilledPolysList() );
650 
651  int error = clearance - outline->Distance( refSeg, ref_seg_width );
652 
653  // to avoid false positive, due to rounding issues and approxiamtions
654  // in distance and clearance calculations, use a small threshold for distance
655  // (1 micron)
656  #define THRESHOLD_DIST Millimeter2iu( 0.001 )
657  if( error > THRESHOLD_DIST )
658  {
660  getLocation( aRefSeg, zone ), aRefSeg, zone ) );
661  }
662  }
663  }
664 
665  /***********************************************/
666  /* Phase 4: test DRC with to board edge */
667  /***********************************************/
668  {
669  SEG test_seg( aRefSeg->GetStart(), aRefSeg->GetEnd() );
670 
671  int clearance = std::max( ref_seg_clearance, dsnSettings.m_CopperEdgeClearance );
672 
673  // the minimum distance = clearance plus half the reference track width
674  SEG::ecoord w_dist = clearance + ref_seg_width / 2;
675  SEG::ecoord w_dist_sq = w_dist * w_dist;
676 
677  for( auto it = m_board_outlines.IterateSegmentsWithHoles(); it; it++ )
678  {
679  if( test_seg.SquaredDistance( *it ) < w_dist_sq )
680  {
681  VECTOR2I pt = test_seg.NearestPoint( *it );
682 
683  KICAD_T types[] = { PCB_LINE_T, EOT };
684  DRAWSEGMENT* edge = nullptr;
685  INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
686  {
687  DRAWSEGMENT* test_edge = dynamic_cast<DRAWSEGMENT*>( item );
688 
689  if( !test_edge || test_edge->GetLayer() != Edge_Cuts )
691 
692  if( test_edge->HitTest((wxPoint) pt, w_dist ) )
693  {
694  edge = test_edge;
695  return SEARCH_RESULT::QUIT;
696  }
697 
699  };
700 
701  // Best-efforts search for edge segment
702  BOARD::IterateForward<BOARD_ITEM*>( m_pcb->Drawings(), inspector, nullptr, types );
703 
705  aRefSeg, edge ) );
706  }
707  }
708  }
709 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:128
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:686
Too small via size.
Definition: drc.h:63
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
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.
micro vias are not allowed
Definition: drc.h:84
std::function< SEARCH_RESULT(EDA_ITEM *aItem, void *aTestData) > INSPECTOR_FUNC
Typedef INSPECTOR is used to inspect and possibly collect the (search) results of iterating over a li...
Definition: base_struct.h:83
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
track too close to via
Definition: drc.h:48
int m_ycliplo
Definition: drc.h:174
const wxPoint & GetStart() const
Definition: class_track.h:111
VECTOR2I::extended_type ecoord
Definition: seg.h:42
int m_ycliphi
Definition: drc.h:176
int m_segmLength
Definition: drc.h:168
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
EDA_UNITS userUnits() const
Definition: drc.h:196
Too small micro via size.
Definition: drc.h:64
track ends are too close
Definition: drc.h:51
tracks are crossing
Definition: drc.h:53
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
#define THRESHOLD_DIST
wxPoint m_padToTestPos
Definition: drc.h:159
via too close to via
Definition: drc.h:49
2 parallel track segments too close: segm ends between segref ends
Definition: drc.h:52
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
BOARD * m_pcb
Definition: drc.h:179
bool SegmentIntersectsSegment(const wxPoint &a_p1_l1, const wxPoint &a_p2_l1, const wxPoint &a_p1_l2, const wxPoint &a_p2_l2, wxPoint *aIntersectionPoint=nullptr)
Test if two lines intersect.
Definition: trigo.cpp:61
bool checkLine(wxPoint aSegStart, wxPoint aSegEnd)
Function checkLine (helper function used in drc calculations to see if one track is in contact with a...
track too close to board edge
Definition: drc.h:88
PCB_LAYER_ID
A quick note on layer IDs:
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Too small track width.
Definition: drc.h:62
LSET is a set of PCB_LAYER_IDs.
const wxPoint GetPosition() const override
Definition: class_track.h:102
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:229
SHAPE_POLY_SET.
pad too close to track
Definition: drc.h:47
static bool checkMarginToCircle(wxPoint aCentre, int aRadius, int aLength)
Check the distance from a point to a segment.
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
bool m_reportAllTrackErrors
Definition: drc.h:152
thru hole is too close to track
Definition: drc.h:46
Too small micro via drill.
Definition: drc.h:66
via's hole is bigger than its diameter
Definition: drc.h:55
virtual int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
int m_xcliphi
Definition: drc.h:175
const wxPoint GetPosition() const override
Definition: class_track.h:389
micro via's layer pair incorrect (layers must be adjacent)
Definition: drc.h:56
Definition: seg.h:39
bool checkClearanceSegmToPad(const D_PAD *aPad, int aSegmentWidth, int aMinDist)
Check the distance from a pad to segment.
Too small via drill.
Definition: drc.h:65
wxPoint m_segmEnd
Definition: drc.h:160
SHAPE_POLY_SET m_board_outlines
Definition: drc.h:180
ZONE_CONTAINERS & Zones()
Definition: class_board.h:243
int GetWidth() const
Definition: class_track.h:105
std::shared_ptr< NETCLASS > GetNetClass() const
Function GetNetClass returns the NETCLASS for this item.
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
track & zone collide or are too close together
Definition: drc.h:79
via too close to track
Definition: drc.h:50
VIATYPE GetViaType() const
Definition: class_track.h:416
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
const wxPoint & GetEnd() const
Definition: class_track.h:108
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:162
bool m_MicroViasAllowed
true to allow micro vias
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
buried vias are not allowed
Definition: drc.h:85
int m_xcliplo
Definition: drc.h:173
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
int GetCopperLayerCount() const
Function GetCopperLayerCount.
DRAWINGS & Drawings()
Definition: class_board.h:238
double m_segmAngle
Definition: drc.h:167
virtual LSET GetLayerSet() const
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
wxPoint getLocation(TRACK *aTrack, ZONE_CONTAINER *aConflictZone) const
Fetches a reasonable point for marking a violoation between two non-point objects.

References addMarkerToPcb(), LSET::AllCuMask(), PNS::angle(), ArcTangente(), B_Cu, BLIND_BURIED, checkClearanceSegmToPad(), checkLine(), checkMarginToCircle(), CONTINUE, SHAPE_POLY_SET::Distance(), BOARD::Drawings(), DRCE_BURIED_VIA_NOT_ALLOWED, DRCE_MICRO_VIA_INCORRECT_LAYER_PAIR, DRCE_MICRO_VIA_NOT_ALLOWED, DRCE_TOO_SMALL_MICROVIA, DRCE_TOO_SMALL_MICROVIA_DRILL, DRCE_TOO_SMALL_TRACK_WIDTH, DRCE_TOO_SMALL_VIA, DRCE_TOO_SMALL_VIA_DRILL, DRCE_TRACK_ENDS, DRCE_TRACK_NEAR_EDGE, DRCE_TRACK_NEAR_PAD, DRCE_TRACK_NEAR_THROUGH_HOLE, DRCE_TRACK_NEAR_VIA, DRCE_TRACK_NEAR_ZONE, DRCE_TRACK_SEGMENTS_TOO_CLOSE, DRCE_TRACKS_CROSSING, DRCE_VIA_HOLE_BIGGER, DRCE_VIA_NEAR_TRACK, DRCE_VIA_NEAR_VIA, Edge_Cuts, EOT, EuclideanNorm(), F_Cu, TRACK::GetClearance(), BOARD_DESIGN_SETTINGS::GetCopperLayerCount(), BOARD::GetDesignSettings(), VIA::GetDrillValue(), TRACK::GetEnd(), BOARD_ITEM::GetLayer(), BOARD_ITEM::GetLayerSet(), getLocation(), BOARD_CONNECTED_ITEM::GetNetClass(), BOARD_CONNECTED_ITEM::GetNetCode(), TRACK::GetPosition(), D_PAD::GetPosition(), VIA::GetPosition(), TRACK::GetStart(), VIA::GetViaType(), TRACK::GetWidth(), DRAWSEGMENT::HitTest(), In1_Cu, SHAPE_POLY_SET::IterateSegmentsWithHoles(), VIA::LayerPair(), BOARD_DESIGN_SETTINGS::m_BlindBuriedViaAllowed, m_board_outlines, BOARD_DESIGN_SETTINGS::m_CopperEdgeClearance, BOARD_DESIGN_SETTINGS::m_MicroViasAllowed, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, m_padToTestPos, m_pcb, m_reportAllTrackErrors, m_segmAngle, m_segmEnd, m_segmLength, BOARD_DESIGN_SETTINGS::m_TrackMinWidth, BOARD_DESIGN_SETTINGS::m_ViasMinDrill, BOARD_DESIGN_SETTINGS::m_ViasMinSize, m_xcliphi, m_xcliplo, m_ycliphi, m_ycliplo, MICROVIA, BOARD::Modules(), PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CIRCLE, PAD_SHAPE_OVAL, PCB_LINE_T, PCB_VIA_T, QUIT, RotatePoint(), SegmentIntersectsSegment(), D_PAD::SetLayerSet(), D_PAD::SetOrientation(), D_PAD::SetPosition(), D_PAD::SetShape(), D_PAD::SetSize(), THRESHOLD_DIST, EDA_ITEM::Type(), userUnits(), wxPoint::x, wxPoint::y, and BOARD::Zones().

Referenced by testTracks().

◆ EditingModules()

bool PCB_TOOL_BASE::EditingModules ( ) const
inlineinherited

◆ frame()

PCB_BASE_EDIT_FRAME* PCB_TOOL_BASE::frame ( ) const
inlineprotectedinherited

Definition at line 150 of file pcb_tool_base.h.

151  {
152  return getEditFrame<PCB_BASE_EDIT_FRAME>();
153  }

Referenced by POINT_EDITOR::addCorner(), MICROWAVE_TOOL::addMicrowaveFootprint(), AUTOPLACE_TOOL::autoplace(), PCB_TOOL_BASE::canvas(), ZONE_FILLER_TOOL::CheckAllZones(), PNS::TOOL_BASE::checkSnap(), PAD_TOOL::copyPadSettings(), EDIT_TOOL::copyToClipboard(), MICROWAVE_TOOL::createInductorBetween(), ROUTER_TOOL::CustomTrackWidthDialog(), MODULE_EDITOR_TOOLS::DeleteFootprint(), PCB_TOOL_BASE::displayOptions(), PCB_TOOL_BASE::doInteractiveItemPlacement(), ROUTER_TOOL::DpDimensionsDialog(), DRAWING_TOOL::drawArc(), DRAWING_TOOL::DrawDimension(), MICROWAVE_TOOL::drawMicrowaveInductor(), DRAWING_TOOL::drawSegment(), DRAWING_TOOL::DrawVia(), DRAWING_TOOL::DrawZone(), PAD_TOOL::EnumeratePads(), PCB_EDITOR_CONTROL::ExportSpecctraDSN(), ROUTER_TOOL::finishInteractive(), EDIT_TOOL::Flip(), PCB_EDITOR_CONTROL::FlipPcbView(), GLOBAL_EDIT_TOOL::GlobalDeletions(), MODULE_EDITOR_TOOLS::ImportFootprint(), PCB_EDITOR_CONTROL::ImportSpecctraSession(), SELECTION_TOOL::Init(), EDIT_TOOL::Init(), ROUTER_TOOL::InlineBreakTrack(), ROUTER_TOOL::InlineDrag(), ROUTER_TOOL::MainLoop(), LENGTH_TUNER_TOOL::MainLoop(), LENGTH_TUNER_TOOL::meanderSettingsDialog(), EDIT_TOOL::MeasureTool(), EDIT_TOOL::Move(), POINT_EDITOR::OnSelectionChange(), ROUTER_TOOL::onViaCommand(), PCBNEW_CONTROL::Paste(), PAD_TOOL::pastePadProperties(), ROUTER_TOOL::performDragging(), ROUTER_TOOL::performRouting(), LENGTH_TUNER_TOOL::performTuning(), EDIT_TOOL::pickCopyReferencePoint(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), DRAWING_TOOL::PlaceText(), ROUTER_TOOL::prepareInteractive(), PAD_TOOL::pushPadSettings(), POSITION_RELATIVE_TOOL::RelativeItemSelectionMove(), EDIT_TOOL::Remove(), POINT_EDITOR::removeCorner(), PNS::TOOL_BASE::Reset(), ROUTER_TOOL::SelectCopperLayerPair(), POSITION_RELATIVE_TOOL::SelectPositionRelativeItem(), POINT_EDITOR::setEditedPoint(), ROUTER_TOOL::SettingsDialog(), GLOBAL_EDIT_TOOL::swapBoardItem(), GLOBAL_EDIT_TOOL::SwapLayers(), ROUTER_TOOL::switchLayerOnViaPlacement(), POINT_EDITOR::updateItem(), PCB_EDITOR_CONTROL::UpdateSchematicFromPCB(), ZONE_FILLER_TOOL::ZoneFill(), and ZONE_FILLER_TOOL::ZoneFillAll().

◆ getEditFrame()

template<typename T >
T* TOOL_BASE::getEditFrame ( ) const
inlineprotectedinherited

Function getEditFrame()

Returns the application window object, casted to requested user type.

Definition at line 186 of file tool_base.h.

187  {
188 #if !defined( QA_TEST ) // Dynamic casts give the linker a siezure in the test framework
189  wxASSERT( dynamic_cast<T*>( getEditFrameInt() ) );
190 #endif
191  return static_cast<T*>( getEditFrameInt() );
192  }
EDA_BASE_FRAME * getEditFrameInt() const
Definition: tool_base.cpp:48

References TOOL_BASE::getEditFrameInt().

Referenced by ZONE_CREATE_HELPER::createNewZone().

◆ GetId()

TOOL_ID TOOL_BASE::GetId ( ) const
inlineinherited

Function GetId() Returns the unique identifier of the tool.

The identifier is set by an instance of TOOL_MANAGER.

Returns
Identifier of the tool.

Definition at line 120 of file tool_base.h.

121  {
122  return m_toolId;
123  }
TOOL_ID m_toolId
Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
Definition: tool_base.h:213

References TOOL_BASE::m_toolId.

Referenced by TOOL_MANAGER::finishTool(), TOOL_MANAGER::InitTools(), TOOL_MANAGER::isActive(), TOOL_MANAGER::RegisterTool(), ACTION_MANAGER::RunHotKey(), TOOL_MANAGER::runTool(), TOOL_MANAGER::saveViewControls(), and TOOL_MANAGER::ShutdownTool().

◆ getLocation() [1/2]

wxPoint DRC::getLocation ( TRACK aTrack,
ZONE_CONTAINER aConflictZone 
) const
private

Fetches a reasonable point for marking a violoation between two non-point objects.

Definition at line 1400 of file pcbnew/drc/drc.cpp.

1401 {
1402  SHAPE_POLY_SET* conflictOutline;
1403 
1404  if( aConflictZone->IsFilled() )
1405  conflictOutline = const_cast<SHAPE_POLY_SET*>( &aConflictZone->GetFilledPolysList() );
1406  else
1407  conflictOutline = aConflictZone->Outline();
1408 
1409  wxPoint pt1 = aTrack->GetPosition();
1410  wxPoint pt2 = aTrack->GetEnd();
1411 
1412  // If the mid-point is in the zone, then that's a fine place for the marker
1413  if( conflictOutline->Distance( ( pt1 + pt2 ) / 2 ) == 0 )
1414  return ( pt1 + pt2 ) / 2;
1415 
1416  // Otherwise do a binary search for a "good enough" marker location
1417  else
1418  {
1419  while( GetLineLength( pt1, pt2 ) > EPSILON )
1420  {
1421  if( conflictOutline->Distance( pt1 ) < conflictOutline->Distance( pt2 ) )
1422  pt2 = ( pt1 + pt2 ) / 2;
1423  else
1424  pt1 = ( pt1 + pt2 ) / 2;
1425  }
1426 
1427  // Once we're within EPSILON pt1 and pt2 are "equivalent"
1428  return pt1;
1429  }
1430 }
bool IsFilled() const
Definition: class_zone.h:188
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:206
SHAPE_POLY_SET * Outline()
Definition: class_zone.h:265
const int EPSILON
const wxPoint GetPosition() const override
Definition: class_track.h:102
SHAPE_POLY_SET.
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
const wxPoint & GetEnd() const
Definition: class_track.h:108
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:571

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

Referenced by doTrackDrc(), testCopperDrawItem(), testCopperTextItem(), and testKeepoutAreas().

◆ getLocation() [2/2]

wxPoint DRC::getLocation ( TRACK aTrack,
BOARD_ITEM aConflitItem,
const SEG aConflictSeg 
) const
private

Definition at line 1433 of file pcbnew/drc/drc.cpp.

1434 {
1435  wxPoint pt1 = aTrack->GetPosition();
1436  wxPoint pt2 = aTrack->GetEnd();
1437 
1438  // Do a binary search along the track for a "good enough" marker location
1439  while( GetLineLength( pt1, pt2 ) > EPSILON )
1440  {
1441  if( aConflictSeg.Distance( pt1 ) < aConflictSeg.Distance( pt2 ) )
1442  pt2 = ( pt1 + pt2 ) / 2;
1443  else
1444  pt1 = ( pt1 + pt2 ) / 2;
1445  }
1446 
1447  // Once we're within EPSILON pt1 and pt2 are "equivalent"
1448  return pt1;
1449 }
int Distance(const SEG &aSeg) const
Function Distance()
Definition: seg.h:202
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:206
const int EPSILON
const wxPoint GetPosition() const override
Definition: class_track.h:102
const wxPoint & GetEnd() const
Definition: class_track.h:108

References SEG::Distance(), EPSILON, TRACK::GetEnd(), GetLineLength(), and TRACK::GetPosition().

◆ GetManager()

TOOL_MANAGER* TOOL_BASE::GetManager ( ) const
inlineinherited

Function GetManager() Returns the instance of TOOL_MANAGER that takes care of the tool.

Returns
Instance of the TOOL_MANAGER. If there is no TOOL_MANAGER associated, it returns NULL.

Definition at line 142 of file tool_base.h.

143  {
144  return m_toolMgr;
145  }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218

References TOOL_BASE::m_toolMgr.

Referenced by BOARD_COMMIT::BOARD_COMMIT(), ZONE_CREATE_HELPER::commitZone(), ZONE_CREATE_HELPER::createNewZone(), PCB_TOOL_BASE::doInteractiveItemPlacement(), ACTION_MENU::getToolManager(), LIB_TREE::onContextMenu(), ZONE_CREATE_HELPER::OnFirstPoint(), ACTION_MENU::OnMenuEvent(), and ZONE_CREATE_HELPER::performZoneCutout().

◆ getModel()

template<typename T >
T* TOOL_BASE::getModel ( ) const
inlineprotectedinherited

Function getModel()

Returns the model object if it matches the requested type.

Definition at line 200 of file tool_base.h.

201  {
202  EDA_ITEM* m = getModelInt();
203 #if !defined( QA_TEST ) // Dynamic casts give the linker a siezure in the test framework
204  wxASSERT( dynamic_cast<T*>( m ) );
205 #endif
206  return static_cast<T*>( m );
207  }
EDA_ITEM * getModelInt() const
Definition: tool_base.cpp:54
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166

References TOOL_BASE::getModelInt().

Referenced by ZONE_CREATE_HELPER::commitZone(), ZONE_CREATE_HELPER::createNewZone(), ZONE_CREATE_HELPER::createZoneFromExisting(), and ZONE_CREATE_HELPER::performZoneCutout().

◆ GetName()

const std::string& TOOL_BASE::GetName ( void  ) const
inlineinherited

Function GetName() Returns the name of the tool.

Tool names are expected to obey the format: application.ToolName (eg. pcbnew.InteractiveSelection).

Returns
The name of the tool.

Definition at line 131 of file tool_base.h.

132  {
133  return m_toolName;
134  }
std::string m_toolName
Name of the tool.
Definition: tool_base.h:217

References TOOL_BASE::m_toolName.

Referenced by TOOL_MANAGER::dispatchInternal(), TOOL_MANAGER::InitTools(), TOOL_MANAGER::invokeTool(), and TOOL_MANAGER::RegisterTool().

◆ GetToolMenu()

◆ GetType()

TOOL_TYPE TOOL_BASE::GetType ( ) const
inlineinherited

Function GetType() Returns the type of the tool.

Returns
The type of the tool.

Definition at line 109 of file tool_base.h.

110  {
111  return m_type;
112  }
TOOL_TYPE m_type
Stores the type of the tool.
Definition: tool_base.h:210

References TOOL_BASE::m_type.

Referenced by TOOL_MANAGER::finishTool(), TOOL_MANAGER::InvokeTool(), TOOL_MANAGER::ResetTools(), TOOL_MANAGER::runTool(), and TOOL_MANAGER::ShutdownTool().

◆ getView()

KIGFX::VIEW * TOOL_BASE::getView ( ) const
protectedinherited

Function getView()

Returns the instance of VIEW object used in the application. It allows tools to draw.

Returns
The instance of VIEW.

Definition at line 36 of file tool_base.cpp.

37 {
38  return m_toolMgr->GetView();
39 }
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:280
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218

References TOOL_MANAGER::GetView(), and TOOL_BASE::m_toolMgr.

Referenced by EE_POINT_EDITOR::addCornerCondition(), ALIGN_DISTRIBUTE_TOOL::AlignLeft(), ALIGN_DISTRIBUTE_TOOL::AlignRight(), COMMON_TOOLS::CenterContents(), EE_SELECTION_TOOL::ClearSelection(), COMMON_TOOLS::CursorControl(), LIB_EDIT_TOOL::DeleteItemCursor(), SCH_EDIT_TOOL::DeleteItemCursor(), PCBNEW_CONTROL::DeleteItemCursor(), GERBVIEW_SELECTION_TOOL::disambiguationMenu(), EE_SELECTION_TOOL::doSelectionMenu(), SELECTION_TOOL::doSelectionMenu(), MICROWAVE_TOOL::drawMicrowaveInductor(), PCB_EDITOR_CONTROL::DrillOrigin(), LIB_EDIT_TOOL::Duplicate(), PAD_TOOL::EnumeratePads(), EE_SELECTION_TOOL::GetNode(), ROUTER_TOOL::getStartLayer(), COMMON_TOOLS::GridPreset(), PCBNEW_CONTROL::GridResetOrigin(), PCBNEW_CONTROL::GridSetOrigin(), SELECTION_TOOL::GuessSelectionCandidates(), EE_SELECTION_TOOL::highlight(), SELECTION_TOOL::highlight(), GERBVIEW_CONTROL::HighlightControl(), PNS::TOOL_BASE::highlightNet(), PCB_INSPECTION_TOOL::highlightNet(), EE_POINT_EDITOR::Main(), CVPCB_FOOTPRINT_VIEWER_SELECTION_TOOL::MeasureTool(), GERBVIEW_SELECTION_TOOL::MeasureTool(), EDIT_TOOL::MeasureTool(), SCH_EDIT_TOOL::Mirror(), EDIT_TOOL::MoveExact(), SCH_MOVE_TOOL::moveItem(), POINT_EDITOR::OnSelectionChange(), COMMON_TOOLS::PanControl(), LIB_EDIT_TOOL::Paste(), SCH_EDITOR_CONTROL::Paste(), PNS::TOOL_BASE::pickSingleItem(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), SCH_EDIT_TOOL::Properties(), EDIT_TOOL::Remove(), PCB_EDITOR_CONTROL::Reset(), PNS::TOOL_BASE::Reset(), PCBNEW_CONTROL::Reset(), GERBVIEW_SELECTION_TOOL::Reset(), DRAWING_TOOL::Reset(), EE_SELECTION_TOOL::Reset(), SELECTION_TOOL::Reset(), EE_TOOL_BASE< SCH_BASE_FRAME >::Reset(), SCH_EDIT_TOOL::Rotate(), GERBVIEW_SELECTION_TOOL::select(), SELECTION_TOOL::Selectable(), GERBVIEW_SELECTION_TOOL::selectable(), EE_SELECTION_TOOL::selectionContains(), SELECTION_TOOL::selectionContains(), EE_SELECTION_TOOL::selectMultiple(), SELECTION_TOOL::selectMultiple(), EE_SELECTION_TOOL::SelectPoint(), ZOOM_TOOL::selectRegion(), GERBVIEW_SELECTION_TOOL::selectVisually(), COMMON_TOOLS::ToggleGrid(), SCH_EDITOR_CONTROL::ToggleHiddenPins(), EE_SELECTION_TOOL::unhighlight(), SELECTION_TOOL::unhighlight(), GERBVIEW_SELECTION_TOOL::unselect(), GERBVIEW_SELECTION_TOOL::unselectVisually(), EE_POINT_EDITOR::updateEditedPoint(), POINT_EDITOR::updateEditedPoint(), SCH_EDITOR_CONTROL::UpdateFind(), PCBNEW_CONTROL::updateGrid(), EE_POINT_EDITOR::updateItem(), SCH_EDITOR_CONTROL::UpdateNetHighlighting(), EE_POINT_EDITOR::updatePoints(), POINT_EDITOR::updatePoints(), SELECTION_TOOL::updateSelection(), PNS::TOOL_BASE::updateStartItem(), EE_TOOL_BASE< SCH_BASE_FRAME >::updateView(), PCB_TOOL_BASE::view(), COMMON_TOOLS::ZoomFitScreen(), SELECTION_TOOL::zoomFitSelection(), EE_SELECTION_TOOL::~EE_SELECTION_TOOL(), GERBVIEW_SELECTION_TOOL::~GERBVIEW_SELECTION_TOOL(), and SELECTION_TOOL::~SELECTION_TOOL().

◆ getViewControls()

KIGFX::VIEW_CONTROLS * TOOL_BASE::getViewControls ( ) const
protectedinherited

Function getViewControls()

Returns the instance of VIEW_CONTROLS object used in the application. It allows tools to read & modify user input and its settings (eg. show cursor, enable snapping to grid, etc.)

Returns
The instance of VIEW_CONTROLS.

Definition at line 42 of file tool_base.cpp.

43 {
44  return m_toolMgr->GetViewControls();
45 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
KIGFX::VIEW_CONTROLS * GetViewControls() const
Definition: tool_manager.h:285

References TOOL_MANAGER::GetViewControls(), and TOOL_BASE::m_toolMgr.

Referenced by EE_POINT_EDITOR::addCorner(), POINT_EDITOR::addCorner(), EE_POINT_EDITOR::addCornerCondition(), SCH_EDIT_TOOL::BreakWire(), PCB_TOOL_BASE::controls(), COMMON_TOOLS::CursorControl(), SCH_LINE_WIRE_BUS_TOOL::doDrawSegments(), SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus(), COMMON_TOOLS::doZoomToPreset(), DRAWING_TOOL::DrawCircle(), DRAWING_TOOL::DrawLine(), MICROWAVE_TOOL::drawMicrowaveInductor(), SCH_LINE_WIRE_BUS_TOOL::DrawSegments(), LIB_DRAWING_TOOLS::DrawShape(), SCH_DRAWING_TOOLS::DrawSheet(), LIB_EDIT_TOOL::Duplicate(), PAD_TOOL::EnumeratePads(), SCH_LINE_WIRE_BUS_TOOL::finishSegments(), COMMON_TOOLS::GridPreset(), PCB_INSPECTION_TOOL::HighlightNet(), SCH_EDITOR_CONTROL::HighlightNet(), PCB_INSPECTION_TOOL::HighlightNetTool(), MODULE_EDITOR_TOOLS::ImportFootprint(), SCH_MOVE_TOOL::Main(), EE_POINT_EDITOR::Main(), LIB_MOVE_TOOL::Main(), CVPCB_FOOTPRINT_VIEWER_SELECTION_TOOL::Main(), PCBNEW_PICKER_TOOL::Main(), PICKER_TOOL::Main(), GERBVIEW_SELECTION_TOOL::Main(), ROUTER_TOOL::MainLoop(), CVPCB_FOOTPRINT_VIEWER_SELECTION_TOOL::MeasureTool(), GERBVIEW_SELECTION_TOOL::MeasureTool(), EDIT_TOOL::MeasureTool(), EDIT_TOOL::Move(), POINT_EDITOR::OnSelectionChange(), LIB_EDIT_TOOL::Paste(), ROUTER_TOOL::performDragging(), LIB_DRAWING_TOOLS::PlaceAnchor(), PCBNEW_CONTROL::placeBoardItems(), SCH_DRAWING_TOOLS::PlaceComponent(), SCH_DRAWING_TOOLS::PlaceImage(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), SCH_EDIT_TOOL::RepeatDrawItem(), EE_SELECTION_TOOL::RequestSelection(), POINT_EDITOR::Reset(), DRAWING_TOOL::Reset(), COMMON_TOOLS::ResetLocalCoords(), GERBVIEW_SELECTION_TOOL::selectCursor(), SELECTION_TOOL::selectCursor(), EE_SELECTION_TOOL::selectMultiple(), SELECTION_TOOL::selectMultiple(), EE_SELECTION_TOOL::SelectNode(), ZOOM_TOOL::selectRegion(), ALIGN_DISTRIBUTE_TOOL::selectTarget(), PICKER_TOOL::setControls(), PCBNEW_PICKER_TOOL::setControls(), EE_POINT_EDITOR::setEditedPoint(), POINT_EDITOR::setEditedPoint(), SCH_DRAWING_TOOLS::SingleClickPlace(), LIB_DRAWING_TOOLS::TwoClickPlace(), SCH_DRAWING_TOOLS::TwoClickPlace(), EE_POINT_EDITOR::updateEditedPoint(), POINT_EDITOR::updateEditedPoint(), LIB_MOVE_TOOL::updateModificationPoint(), EDIT_TOOL::updateModificationPoint(), and COMMON_TOOLS::ZoomCenter().

◆ Go()

template<class T >
void TOOL_INTERACTIVE::Go ( int(T::*)(const TOOL_EVENT &)  aStateFunc,
const TOOL_EVENT_LIST aConditions = TOOL_EVENTTC_ANYTA_ANY ) 
)
inherited

Function Go()

Defines which state (aStateFunc) to go when a certain event arrives (aConditions). No conditions means any event.

Definition at line 129 of file tool_interactive.h.

131 {
132  TOOL_STATE_FUNC sptr = std::bind( aStateFunc, static_cast<T*>( this ), std::placeholders::_1 );
133 
134  goInternal( sptr, aConditions );
135 }
std::function< int(const TOOL_EVENT &)> TOOL_STATE_FUNC
Definition: tool_base.h:57
void goInternal(TOOL_STATE_FUNC &aState, const TOOL_EVENT_LIST &aConditions)

References TOOL_INTERACTIVE::goInternal().

Referenced by LENGTH_TUNER_TOOL::setTransitions(), ZOOM_TOOL::setTransitions(), AUTOPLACE_TOOL::setTransitions(), MICROWAVE_TOOL::setTransitions(), ROUTER_TOOL::setTransitions(), CVPCB_FOOTPRINT_VIEWER_CONTROL::setTransitions(), LIB_PIN_TOOL::setTransitions(), PAD_TOOL::setTransitions(), EE_INSPECTION_TOOL::setTransitions(), ZONE_FILLER_TOOL::setTransitions(), LIB_DRAWING_TOOLS::setTransitions(), EE_POINT_EDITOR::setTransitions(), COMMON_CONTROL::setTransitions(), SCH_MOVE_TOOL::setTransitions(), KICAD_MANAGER_CONTROL::setTransitions(), LIB_MOVE_TOOL::setTransitions(), GERBVIEW_CONTROL::setTransitions(), SCH_DRAWING_TOOLS::setTransitions(), POINT_EDITOR::setTransitions(), GLOBAL_EDIT_TOOL::setTransitions(), CVPCB_FOOTPRINT_VIEWER_SELECTION_TOOL::setTransitions(), EDA_3D_VIEWER_CONTROL::setTransitions(), LIB_EDIT_TOOL::setTransitions(), LIB_CONTROL::setTransitions(), SCH_EDIT_TOOL::setTransitions(), POSITION_RELATIVE_TOOL::setTransitions(), GERBVIEW_SELECTION_TOOL::setTransitions(), COMMON_TOOLS::setTransitions(), PCB_INSPECTION_TOOL::setTransitions(), PCBNEW_CONTROL::setTransitions(), ALIGN_DISTRIBUTE_TOOL::setTransitions(), SCH_LINE_WIRE_BUS_TOOL::setTransitions(), MODULE_EDITOR_TOOLS::setTransitions(), CVPCB_CONTROL::setTransitions(), CVPCB_ASSOCIATION_TOOL::setTransitions(), PCBNEW_PICKER_TOOL::setTransitions(), PICKER_TOOL::setTransitions(), PCB_EDITOR_CONTROL::setTransitions(), DRAWING_TOOL::setTransitions(), EDIT_TOOL::setTransitions(), SELECTION_TOOL::setTransitions(), SCH_EDITOR_CONTROL::setTransitions(), setTransitions(), and EE_SELECTION_TOOL::setTransitions().

◆ Init()

bool PCB_TOOL_BASE::Init ( )
overridevirtualinherited

Function Init() Init() is called once upon a registration of the tool.

Returns
True if the initialization went fine, false - otherwise.

Reimplemented from TOOL_BASE.

Reimplemented in EDIT_TOOL, SELECTION_TOOL, DRAWING_TOOL, POSITION_RELATIVE_TOOL, PCB_EDITOR_CONTROL, POINT_EDITOR, MODULE_EDITOR_TOOLS, GLOBAL_EDIT_TOOL, PAD_TOOL, PCB_INSPECTION_TOOL, and ROUTER_TOOL.

Definition at line 232 of file pcb_tool_base.cpp.

233 {
234  // A basic context manu. Many (but not all) tools will choose to override this.
235 
236  auto& ctxMenu = m_menu.GetMenu();
237 
238  // cancel current tool goes in main context menu at the top if present
240  ctxMenu.AddSeparator( 1 );
241 
242  // Finally, add the standard zoom/grid items
243  getEditFrame<PCB_BASE_FRAME>()->AddStandardSubMenus( m_menu );
244 
245  return true;
246 }
static bool ShowAlways(const SELECTION &aSelection)
Function ShowAlways The default condition function (always returns true).
TOOL_MENU m_menu
functions below are not yet implemented - their interface may change
CONDITIONAL_MENU & GetMenu()
Function GetMenu.
Definition: tool_menu.cpp:46
static TOOL_ACTION cancelInteractive
Definition: actions.h:65
void AddItem(const TOOL_ACTION &aAction, const SELECTION_CONDITION &aCondition, int aOrder=ANY_ORDER)
Function AddItem()

References CONDITIONAL_MENU::AddItem(), ACTIONS::cancelInteractive, TOOL_MENU::GetMenu(), TOOL_INTERACTIVE::m_menu, and SELECTION_CONDITIONS::ShowAlways().

◆ IsDRCDialogShown()

bool DRC::IsDRCDialogShown ( )

Check to see if the DRC dialog is currently shown.

Returns
true if the dialog is shown

Definition at line 152 of file pcbnew/drc/drc.cpp.

153 {
154  if( m_drcDialog )
155  return m_drcDialog->IsShown();
156 
157  return false;
158 }
DIALOG_DRC * m_drcDialog
Definition: drc.h:181

References m_drcDialog.

◆ IsToolActive()

bool TOOL_BASE::IsToolActive ( ) const
inherited

Definition at line 31 of file tool_base.cpp.

32 {
33  return m_toolMgr->IsToolActive( m_toolId );
34 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
TOOL_ID m_toolId
Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
Definition: tool_base.h:213
bool IsToolActive(TOOL_ID aId) const
Function IsToolActive() Returns true if a tool with given id is active (executing)

References TOOL_MANAGER::IsToolActive(), TOOL_BASE::m_toolId, and TOOL_BASE::m_toolMgr.

◆ module()

◆ Reset()

void DRC::Reset ( RESET_REASON  aReason)
overridevirtual

Function Reset() Brings the tool to a known, initial state.

If the tool claimed anything from the model or the view, it must release it when its reset.

Parameters
aReasoncontains information about the reason of tool reset.

Reimplemented from PCB_TOOL_BASE.

Definition at line 96 of file pcbnew/drc/drc.cpp.

97 {
98  m_pcbEditorFrame = getEditFrame<PCB_EDIT_FRAME>();
99 
100  if( aReason == MODEL_RELOAD )
101  {
102  if( m_drcDialog )
103  DestroyDRCDialog( wxID_OK );
104 
106  }
107 }
void DestroyDRCDialog(int aReason)
Deletes this ui dialog box and zeros out its pointer to remember the state of the dialog's existence.
Model changes (required full reload)
Definition: tool_base.h:81
BOARD * m_pcb
Definition: drc.h:179
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
DIALOG_DRC * m_drcDialog
Definition: drc.h:181
BOARD * GetBoard() const

References DestroyDRCDialog(), PCB_BASE_FRAME::GetBoard(), m_drcDialog, m_pcb, m_pcbEditorFrame, and TOOL_BASE::MODEL_RELOAD.

◆ RunMainStack()

void TOOL_INTERACTIVE::RunMainStack ( std::function< void()>  aFunc)
inherited

Function RunMainStack()

Calls a function using the main stack.

Parameters
aFuncis the function to be calls.

Definition at line 87 of file tool_interactive.cpp.

88 {
89  m_toolMgr->RunMainStack( this, std::move( aFunc ) );
90 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
void RunMainStack(TOOL_BASE *aTool, std::function< void()> aFunc)

References TOOL_BASE::m_toolMgr, and TOOL_MANAGER::RunMainStack().

Referenced by DRAWING_TOOL::PlaceText().

◆ RunTests()

void DRC::RunTests ( wxTextCtrl *  aMessages = NULL)

Run all the tests specified with a previous call to SetSettings()

Parameters
aMessages= a wxTextControl where to display some activity messages. Can be NULL

Definition at line 321 of file pcbnew/drc/drc.cpp.

322 {
323  // be sure m_pcb is the current board, not a old one
324  // ( the board can be reloaded )
326 
327  if( aMessages )
328  {
329  aMessages->AppendText( _( "Board Outline...\n" ) );
330  wxSafeYield();
331  }
332 
333  testOutline();
334 
335  // someone should have cleared the two lists before calling this.
336  if( !testNetClasses() )
337  {
338  // testing the netclasses is a special case because if the netclasses
339  // do not pass the BOARD_DESIGN_SETTINGS checks, then every member of a net
340  // class (a NET) will cause its items such as tracks, vias, and pads
341  // to also fail. So quit after *all* netclass errors have been reported.
342  if( aMessages )
343  aMessages->AppendText( _( "Aborting\n" ) );
344 
345  // update the m_drcDialog listboxes
346  updatePointers();
347 
348  return;
349  }
350 
351  // test pad to pad clearances, nothing to do with tracks, vias or zones.
352  if( m_doPad2PadTest )
353  {
354  if( aMessages )
355  {
356  aMessages->AppendText( _( "Pad clearances...\n" ) );
357  wxSafeYield();
358  }
359 
360  testPad2Pad();
361  }
362 
363  // test clearances between drilled holes
364  if( aMessages )
365  {
366  aMessages->AppendText( _( "Drill clearances...\n" ) );
367  wxSafeYield();
368  }
369 
371 
372  // caller (a wxTopLevelFrame) is the wxDialog or the Pcb Editor frame that call DRC:
373  wxWindow* caller = aMessages ? aMessages->GetParent() : m_pcbEditorFrame;
374 
375  if( m_refillZones )
376  {
377  if( aMessages )
378  aMessages->AppendText( _( "Refilling all zones...\n" ) );
379 
380  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->FillAllZones( caller );
381  }
382  else
383  {
384  if( aMessages )
385  aMessages->AppendText( _( "Checking zone fills...\n" ) );
386 
387  m_toolMgr->GetTool<ZONE_FILLER_TOOL>()->CheckAllZones( caller );
388  }
389 
390  // test track and via clearances to other tracks, pads, and vias
391  if( aMessages )
392  {
393  aMessages->AppendText( _( "Track clearances...\n" ) );
394  wxSafeYield();
395  }
396 
397  testTracks( aMessages ? aMessages->GetParent() : m_pcbEditorFrame, true );
398 
399  // test zone clearances to other zones
400  if( aMessages )
401  {
402  aMessages->AppendText( _( "Zone to zone clearances...\n" ) );
403  wxSafeYield();
404  }
405 
406  testZones();
407 
408  // find and gather unconnected pads.
409  if( m_doUnconnectedTest )
410  {
411  if( aMessages )
412  {
413  aMessages->AppendText( _( "Unconnected pads...\n" ) );
414  aMessages->Refresh();
415  }
416 
417  testUnconnected();
418  }
419 
420  // find and gather vias, tracks, pads inside keepout areas.
421  if( m_doKeepoutTest )
422  {
423  if( aMessages )
424  {
425  aMessages->AppendText( _( "Keepout areas ...\n" ) );
426  aMessages->Refresh();
427  }
428 
430  }
431 
432  // find and gather vias, tracks, pads inside text boxes.
433  if( aMessages )
434  {
435  aMessages->AppendText( _( "Text and graphic clearances...\n" ) );
436  wxSafeYield();
437  }
438 
440 
441  // find overlapping courtyard ares.
444  {
445  if( aMessages )
446  {
447  aMessages->AppendText( _( "Courtyard areas...\n" ) );
448  aMessages->Refresh();
449  }
450 
452  }
453 
454  for( DRC_ITEM* footprintItem : m_footprints )
455  delete footprintItem;
456 
457  m_footprints.clear();
458  m_footprintsTested = false;
459 
460  if( m_testFootprints && !Kiface().IsSingle() )
461  {
462  if( aMessages )
463  {
464  aMessages->AppendText( _( "Checking footprints against schematic...\n" ) );
465  aMessages->Refresh();
466  }
467 
468  NETLIST netlist;
470 
471  if( m_drcDialog )
472  m_drcDialog->Raise();
473 
475  m_footprintsTested = true;
476  }
477 
478  // Check if there are items on disabled layers
480 
481  if( aMessages )
482  {
483  aMessages->AppendText( _( "Items on disabled layers...\n" ) );
484  aMessages->Refresh();
485  }
486 
487  m_drcRun = true;
488 
489  // update the m_drcDialog listboxes
490  updatePointers();
491 
492  if( aMessages )
493  {
494  // no newline on this one because it is last, don't want the window
495  // to unnecessarily scroll.
496  aMessages->AppendText( _( "Finished" ) );
497  }
498 }
bool m_refillZones
Definition: drc.h:151
std::vector< DRC_ITEM * > m_footprints
Definition: drc.h:184
static void TestFootprints(NETLIST &aNetlist, BOARD *aPCB, EDA_UNITS aUnits, std::vector< DRC_ITEM * > &aDRCList)
Test the board footprints against a netlist.
void testCopperTextAndGraphics()
void doOverlappingCourtyardsDrc()
Test for footprint courtyard overlaps.
void testKeepoutAreas()
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
bool Ignore(int aDRCErrorCode)
returns true if the DRC error code's severity is SEVERITY_IGNORE
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
void testOutline()
Test that the board outline is contiguous and composed of valid elements.
footprint has no courtyard defined
Definition: drc.h:81
BOARD * m_pcb
Definition: drc.h:179
EDA_UNITS GetUserUnits() const
Definition: dialog_shim.h:132
void testDrilledHoles()
bool m_testFootprints
Definition: drc.h:153
bool m_doKeepoutTest
Definition: drc.h:150
ZONE_FILLER_TOOL.
NETLIST stores all of information read from a netlist along with the flags used to update the NETLIST...
Definition: pcb_netlist.h:212
void testZones()
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
bool m_drcRun
Definition: drc.h:185
void testDisabledLayers()
Tests for items placed on disabled layers (causing false connections).
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
bool m_doPad2PadTest
Definition: drc.h:147
void testPad2Pad()
bool m_footprintsTested
Definition: drc.h:186
bool testNetClasses()
Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance ...
void testTracks(wxWindow *aActiveWindow, bool aShowProgressBar)
Perform the DRC on all tracks.
#define _(s)
Definition: 3d_actions.cpp:33
footprint courtyards overlap
Definition: drc.h:80
DIALOG_DRC * m_drcDialog
Definition: drc.h:181
BOARD * GetBoard() const
void testUnconnected()
bool FetchNetlistFromSchematic(NETLIST &aNetlist, FETCH_NETLIST_MODE aMode)
bool m_doUnconnectedTest
Definition: drc.h:148

References _, PCB_EDIT_FRAME::ANNOTATION_DIALOG, doOverlappingCourtyardsDrc(), DRCE_MISSING_COURTYARD_IN_FOOTPRINT, DRCE_OVERLAPPING_FOOTPRINTS, PCB_EDIT_FRAME::FetchNetlistFromSchematic(), PCB_BASE_FRAME::GetBoard(), BOARD::GetDesignSettings(), TOOL_MANAGER::GetTool(), DIALOG_SHIM::GetUserUnits(), BOARD_DESIGN_SETTINGS::Ignore(), Kiface(), m_doKeepoutTest, m_doPad2PadTest, m_doUnconnectedTest, m_drcDialog, m_drcRun, m_footprints, m_footprintsTested, m_pcb, m_pcbEditorFrame, m_refillZones, m_testFootprints, TOOL_BASE::m_toolMgr, testCopperTextAndGraphics(), testDisabledLayers(), testDrilledHoles(), TestFootprints(), testKeepoutAreas(), testNetClasses(), testOutline(), testPad2Pad(), testTracks(), testUnconnected(), testZones(), and updatePointers().

Referenced by DIALOG_DRC::OnRunDRCClick().

◆ selection() [1/2]

const PCBNEW_SELECTION & PCB_TOOL_BASE::selection ( ) const
protectedinherited

Definition at line 270 of file pcb_tool_base.cpp.

271 {
272  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
273  const auto& selection = selTool->GetSelection();
274  return selection;
275 }
SELECTION_TOOL.
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
const PCBNEW_SELECTION & selection() const

References TOOL_MANAGER::GetTool(), and TOOL_BASE::m_toolMgr.

Referenced by AUTOPLACE_TOOL::autoplaceSelected(), PCB_INSPECTION_TOOL::calculateSelectionRatsnest(), ROUTER_TOOL::CanInlineDrag(), EDIT_TOOL::ChangeTrackWidth(), PAD_TOOL::copyPadSettings(), EDIT_TOOL::copyToClipboard(), EDIT_TOOL::CreateArray(), MODULE_EDITOR_TOOLS::CreatePadFromShapes(), PCB_INSPECTION_TOOL::CrossProbePcbToSch(), PCB_TOOL_BASE::doInteractiveItemPlacement(), DRAWING_TOOL::drawArc(), DRAWING_TOOL::DrawDimension(), MICROWAVE_TOOL::drawMicrowaveInductor(), DRAWING_TOOL::drawSegment(), DRAWING_TOOL::DrawZone(), EDIT_TOOL::Duplicate(), EDIT_TOOL::EditFpInFpEditor(), PAD_TOOL::EnumeratePads(), GLOBAL_EDIT_TOOL::ExchangeFootprints(), MODULE_EDITOR_TOOLS::ExplodePadToShapes(), SELECTION_TOOL::filterSelection(), EDIT_TOOL::Flip(), DRAWING_TOOL::getSourceZoneForAction(), PCB_INSPECTION_TOOL::highlightNet(), ROUTER_TOOL::InlineBreakTrack(), ROUTER_TOOL::InlineDrag(), PCB_INSPECTION_TOOL::LocalRatsnestTool(), EDIT_TOOL::Mirror(), PCB_EDITOR_CONTROL::modifyLockSelected(), EDIT_TOOL::Move(), EDIT_TOOL::MoveExact(), POINT_EDITOR::OnSelectionChange(), PAD_TOOL::pastePadProperties(), PCBNEW_CONTROL::placeBoardItems(), DRAWING_TOOL::PlaceImportedGraphics(), PCB_EDITOR_CONTROL::PlaceModule(), PCB_EDITOR_CONTROL::PlaceTarget(), DRAWING_TOOL::PlaceText(), POSITION_RELATIVE_TOOL::PositionRelative(), EDIT_TOOL::Properties(), PAD_TOOL::pushPadSettings(), EDIT_TOOL::Rotate(), PCB_TOOL_BASE::selection(), SELECTION_TOOL::selectNet(), DRAWING_TOOL::SetAnchor(), PCB_EDITOR_CONTROL::TrackWidthDec(), PCB_EDITOR_CONTROL::TrackWidthInc(), PCBNEW_CONTROL::UpdateMessagePanel(), PCB_INSPECTION_TOOL::UpdateSelectionRatsnest(), PCB_EDITOR_CONTROL::ViaSizeDec(), PCB_EDITOR_CONTROL::ViaSizeInc(), PCB_EDITOR_CONTROL::ZoneDuplicate(), ZONE_FILLER_TOOL::ZoneFill(), PCB_EDITOR_CONTROL::ZoneMerge(), and ZONE_FILLER_TOOL::ZoneUnfill().

◆ selection() [2/2]

PCBNEW_SELECTION & PCB_TOOL_BASE::selection ( )
protectedinherited

Definition at line 278 of file pcb_tool_base.cpp.

279 {
280  auto selTool = m_toolMgr->GetTool<SELECTION_TOOL>();
281  auto& selection = selTool->GetSelection();
282  return selection;
283 }
SELECTION_TOOL.
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
const PCBNEW_SELECTION & selection() const

References TOOL_MANAGER::GetTool(), TOOL_BASE::m_toolMgr, and PCB_TOOL_BASE::selection().

◆ SetContextMenu()

void TOOL_INTERACTIVE::SetContextMenu ( ACTION_MENU aMenu,
CONTEXT_MENU_TRIGGER  aTrigger = CMENU_BUTTON 
)
inherited

Function SetContextMenu()

Assigns a context menu and tells when it should be activated.

Parameters
aMenuis the menu to be assigned.
aTriggerdetermines conditions upon which the context menu is activated.

Definition at line 76 of file tool_interactive.cpp.

77 {
78  if( aMenu )
79  aMenu->SetTool( this );
80  else
81  aTrigger = CMENU_OFF;
82 
83  m_toolMgr->ScheduleContextMenu( this, aMenu, aTrigger );
84 }
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
void SetTool(TOOL_INTERACTIVE *aTool)
Function SetTool() Sets a tool that is the creator of the menu.
void ScheduleContextMenu(TOOL_BASE *aTool, ACTION_MENU *aMenu, CONTEXT_MENU_TRIGGER aTrigger)
Sets behaviour of the tool's context popup menu.

References CMENU_OFF, TOOL_BASE::m_toolMgr, TOOL_MANAGER::ScheduleContextMenu(), and ACTION_MENU::SetTool().

Referenced by GERBVIEW_SELECTION_TOOL::disambiguationMenu(), EE_SELECTION_TOOL::doSelectionMenu(), SELECTION_TOOL::doSelectionMenu(), ROUTER_TOOL::MainLoop(), LENGTH_TUNER_TOOL::MainLoop(), TOOL_MENU::ShowContextMenu(), and SCH_LINE_WIRE_BUS_TOOL::UnfoldBus().

◆ SetEditModules()

void PCB_TOOL_BASE::SetEditModules ( bool  aEnabled)
inlineinherited

Function SetEditModules()

Toggles edit module mode. When enabled, one may select parts of modules individually (graphics, pads, etc.), so they can be modified.

Parameters
aEnableddecides if the mode should be enabled.

Definition at line 101 of file pcb_tool_base.h.

102  {
103  m_editModules = aEnabled;
104  }

References PCB_TOOL_BASE::m_editModules.

◆ setTransitions()

void DRC::setTransitions ( )
overrideprivatevirtual

Sets up handlers for various events.

Reimplemented from PCB_TOOL_BASE.

Definition at line 1391 of file pcbnew/drc/drc.cpp.

1392 {
1393  Go( &DRC::ShowDRCDialog, PCB_ACTIONS::runDRC.MakeEvent() );
1394 }
void ShowDRCDialog(wxWindow *aParent)
Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and create...
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Function Go()
static TOOL_ACTION runDRC
Definition: pcb_actions.h:324

References TOOL_INTERACTIVE::Go(), PCB_ACTIONS::runDRC, and ShowDRCDialog().

◆ ShowDRCDialog() [1/2]

void DRC::ShowDRCDialog ( wxWindow *  aParent)

Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and creates the MARKERS.

The dialog is only created if it is not already in existence.

Parameters
aParentis the parent window for wxWidgets. Usually the PCB editor frame but can be another dialog if aParent == NULL (default), the parent will be the PCB editor frame and the dialog will be not modal (just float on parent if aParent is specified, the dialog will be modal. The modal mode is mandatory if the dialog is created from another dialog, not from the PCB editor frame

Definition at line 110 of file pcbnew/drc/drc.cpp.

111 {
112  bool show_dlg_modal = true;
113 
114  // the dialog needs a parent frame. if it is not specified, this is
115  // the PCB editor frame specified in DRC class.
116  if( !aParent )
117  {
118  // if any parent is specified, the dialog is modal.
119  // if this is the default PCB editor frame, it is not modal
120  show_dlg_modal = false;
121  aParent = m_pcbEditorFrame;
122  }
123 
124  Activate();
126 
127  if( !m_drcDialog )
128  {
129  m_drcDialog = new DIALOG_DRC( this, m_pcbEditorFrame, aParent );
130  updatePointers();
131 
132  if( show_dlg_modal )
133  m_drcDialog->ShowModal();
134  else
135  m_drcDialog->Show( true );
136  }
137  else // The dialog is just not visible (because the user has double clicked on an error item)
138  {
139  updatePointers();
140  m_drcDialog->Show( true );
141  }
142 }
static TOOL_ACTION selectionClear
Clears the current selection.
Definition: pcb_actions.h:73
TOOL_MANAGER * m_toolMgr
Definition: tool_base.h:218
bool RunAction(const std::string &aActionName, bool aNow=false, T aParam=NULL)
Function RunAction() Runs the specified action.
Definition: tool_manager.h:139
void updatePointers()
Update needed pointers from the one pointer which is known not to change.
friend class DIALOG_DRC
Definition: drc.h:135
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
bool Show(bool show) override
void Activate()
Function Activate() Runs the tool.
DIALOG_DRC * m_drcDialog
Definition: drc.h:181

References TOOL_INTERACTIVE::Activate(), DIALOG_DRC, m_drcDialog, m_pcbEditorFrame, TOOL_BASE::m_toolMgr, TOOL_MANAGER::RunAction(), PCB_ACTIONS::selectionClear, DIALOG_SHIM::Show(), and updatePointers().

Referenced by DIALOG_PLOT::onRunDRC(), setTransitions(), and ShowDRCDialog().

◆ ShowDRCDialog() [2/2]

int DRC::ShowDRCDialog ( const TOOL_EVENT aEvent)

Definition at line 145 of file pcbnew/drc/drc.cpp.

146 {
147  ShowDRCDialog( nullptr );
148  return 0;
149 }
void ShowDRCDialog(wxWindow *aParent)
Open a dialog and prompts the user, then if a test run button is clicked, runs the test(s) and create...

References ShowDRCDialog().

◆ testCopperDrawItem()

void DRC::testCopperDrawItem ( DRAWSEGMENT aDrawing)
private

Definition at line 940 of file pcbnew/drc/drc.cpp.

941 {
942  std::vector<SEG> itemShape;
943  int itemWidth = aItem->GetWidth();
944 
945  switch( aItem->GetShape() )
946  {
947  case S_ARC:
948  {
949  SHAPE_ARC arc( aItem->GetCenter(), aItem->GetArcStart(), (double) aItem->GetAngle() / 10.0 );
950 
951  auto l = arc.ConvertToPolyline();
952 
953  for( int i = 0; i < l.SegmentCount(); i++ )
954  itemShape.push_back( l.Segment( i ) );
955 
956  break;
957  }
958 
959  case S_SEGMENT:
960  itemShape.emplace_back( SEG( aItem->GetStart(), aItem->GetEnd() ) );
961  break;
962 
963  case S_CIRCLE:
964  {
965  // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
966  SHAPE_ARC circle( aItem->GetCenter(), aItem->GetEnd(), 360.0 );
967 
968  auto l = circle.ConvertToPolyline();
969 
970  for( int i = 0; i < l.SegmentCount(); i++ )
971  itemShape.push_back( l.Segment( i ) );
972 
973  break;
974  }
975 
976  case S_CURVE:
977  {
978  aItem->RebuildBezierToSegmentsPointsList( aItem->GetWidth() );
979  wxPoint start_pt = aItem->GetBezierPoints()[0];
980 
981  for( unsigned int jj = 1; jj < aItem->GetBezierPoints().size(); jj++ )
982  {
983  wxPoint end_pt = aItem->GetBezierPoints()[jj];
984  itemShape.emplace_back( SEG( start_pt, end_pt ) );
985  start_pt = end_pt;
986  }
987 
988  break;
989  }
990 
991  default:
992  break;
993  }
994 
995  // Test tracks and vias
996  for( auto track : m_pcb->Tracks() )
997  {
998  if( !track->IsOnLayer( aItem->GetLayer() ) )
999  continue;
1000 
1001  int minDist = ( track->GetWidth() + itemWidth ) / 2 + track->GetClearance( NULL );
1002  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1003 
1004  for( const auto& itemSeg : itemShape )
1005  {
1006  if( trackAsSeg.Distance( itemSeg ) < minDist )
1007  {
1008  if( track->Type() == PCB_VIA_T )
1009  {
1011  getLocation( track, aItem, itemSeg ),
1012  track, aItem ) );
1013  }
1014  else
1015  {
1017  getLocation( track, aItem, itemSeg ),
1018  track, aItem ) );
1019  }
1020  break;
1021  }
1022  }
1023  }
1024 
1025  // Test pads
1026  for( auto pad : m_pcb->GetPads() )
1027  {
1028  if( !pad->IsOnLayer( aItem->GetLayer() ) )
1029  continue;
1030 
1031  // Graphic items are allowed to act as net-ties within their own footprint
1032  if( pad->GetParent() == aItem->GetParent() )
1033  continue;
1034 
1035  SHAPE_POLY_SET padOutline;
1036  pad->TransformShapeWithClearanceToPolygon( padOutline, pad->GetClearance( NULL ) );
1037 
1038  for( const auto& itemSeg : itemShape )
1039  {
1040  if( padOutline.Distance( itemSeg, itemWidth ) == 0 )
1041  {
1043  pad->GetPosition(), pad, aItem ) );
1044  break;
1045  }
1046  }
1047  }
1048 }
usual segment : line with rounded ends
EDA_UNITS userUnits() const
Definition: drc.h:196
via and copper graphic collide or are too close
Definition: drc.h:77
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
#define NULL
SHAPE_POLY_SET.
Arcs (with rounded ends)
Bezier Curve.
Definition: seg.h:39
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
pad and copper graphic collide or are too close
Definition: drc.h:78
track & copper graphic collide or are too close
Definition: drc.h:76
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:97
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=500.0) const
Constructs a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:274
TRACKS & Tracks()
Definition: class_board.h:220
wxPoint getLocation(TRACK *aTrack, ZONE_CONTAINER *aConflictZone) const
Fetches a reasonable point for marking a violoation between two non-point objects.

References addMarkerToPcb(), SHAPE_ARC::ConvertToPolyline(), SHAPE_POLY_SET::Distance(), DRCE_PAD_NEAR_COPPER, DRCE_TRACK_NEAR_COPPER, DRCE_VIA_NEAR_COPPER, DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetBezierPoints(), DRAWSEGMENT::GetCenter(), DRAWSEGMENT::GetEnd(), BOARD_ITEM::GetLayer(), getLocation(), BOARD::GetPads(), BOARD_ITEM::GetParent(), DRAWSEGMENT::GetShape(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), m_pcb, NULL, PCB_VIA_T, DRAWSEGMENT::RebuildBezierToSegmentsPointsList(), S_ARC, S_CIRCLE, S_CURVE, S_SEGMENT, BOARD::Tracks(), and userUnits().

Referenced by testCopperTextAndGraphics().

◆ testCopperTextAndGraphics()

void DRC::testCopperTextAndGraphics ( )
private

Definition at line 897 of file pcbnew/drc/drc.cpp.

898 {
899  // Test copper items for clearance violations with vias, tracks and pads
900 
901  for( BOARD_ITEM* brdItem : m_pcb->Drawings() )
902  {
903  if( IsCopperLayer( brdItem->GetLayer() ) )
904  {
905  if( brdItem->Type() == PCB_TEXT_T )
906  testCopperTextItem( brdItem );
907  else if( brdItem->Type() == PCB_LINE_T )
908  testCopperDrawItem( static_cast<DRAWSEGMENT*>( brdItem ));
909  }
910  }
911 
912  for( MODULE* module : m_pcb->Modules() )
913  {
914  TEXTE_MODULE& ref = module->Reference();
915  TEXTE_MODULE& val = module->Value();
916 
917  if( ref.IsVisible() && IsCopperLayer( ref.GetLayer() ) )
918  testCopperTextItem( &ref );
919 
920  if( val.IsVisible() && IsCopperLayer( val.GetLayer() ) )
921  testCopperTextItem( &val );
922 
923  if( module->IsNetTie() )
924  continue;
925 
926  for( auto item : module->GraphicalItems() )
927  {
928  if( IsCopperLayer( item->GetLayer() ) )
929  {
930  if( item->Type() == PCB_MODULE_TEXT_T && ( (TEXTE_MODULE*) item )->IsVisible() )
931  testCopperTextItem( item );
932  else if( item->Type() == PCB_MODULE_EDGE_T )
933  testCopperDrawItem( static_cast<DRAWSEGMENT*>( item ));
934  }
935  }
936  }
937 }
TEXTE_MODULE & Reference()
Definition: class_module.h:477
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
bool IsVisible() const
Definition: eda_text.h:170
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void testCopperDrawItem(DRAWSEGMENT *aDrawing)
DRAWINGS & GraphicalItems()
Definition: class_module.h:183
void testCopperTextItem(BOARD_ITEM *aTextItem)
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
BOARD * m_pcb
Definition: drc.h:179
bool IsNetTie() const
Definition: class_module.h:267
MODULES & Modules()
Definition: class_board.h:229
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:476
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
MODULE * module() const
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
DRAWINGS & Drawings()
Definition: class_board.h:238

References BOARD::Drawings(), BOARD_ITEM::GetLayer(), MODULE::GraphicalItems(), IsCopperLayer(), MODULE::IsNetTie(), EDA_TEXT::IsVisible(), m_pcb, PCB_TOOL_BASE::module(), BOARD::Modules(), PCB_LINE_T, PCB_MODULE_EDGE_T, PCB_MODULE_TEXT_T, PCB_TEXT_T, MODULE::Reference(), testCopperDrawItem(), testCopperTextItem(), and MODULE::Value().

Referenced by RunTests().

◆ testCopperTextItem()

void DRC::testCopperTextItem ( BOARD_ITEM aTextItem)
private

Definition at line 1051 of file pcbnew/drc/drc.cpp.

1052 {
1053  EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
1054 
1055  if( text == nullptr )
1056  return;
1057 
1058  std::vector<wxPoint> textShape; // a buffer to store the text shape (set of segments)
1059  int textWidth = text->GetThickness();
1060 
1061  // So far the bounding box makes up the text-area
1062  text->TransformTextShapeToSegmentList( textShape );
1063 
1064  if( textShape.size() == 0 ) // Should not happen (empty text?)
1065  return;
1066 
1067  EDA_RECT bbox = text->GetTextBox();
1068  SHAPE_RECT rect_area( bbox.GetX(), bbox.GetY(), bbox.GetWidth(), bbox.GetHeight() );
1069 
1070  // Test tracks and vias
1071  for( auto track : m_pcb->Tracks() )
1072  {
1073  if( !track->IsOnLayer( aTextItem->GetLayer() ) )
1074  continue;
1075 
1076  int minDist = ( track->GetWidth() + textWidth ) / 2 + track->GetClearance( NULL );
1077  SEG trackAsSeg( track->GetStart(), track->GetEnd() );
1078 
1079  // Fast test to detect a trach segment candidate inside the text bounding box
1080  if( !rect_area.Collide( trackAsSeg, minDist ) )
1081  continue;
1082 
1083  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1084  {
1085  SEG textSeg( textShape[jj], textShape[jj+1] );
1086 
1087  if( trackAsSeg.Distance( textSeg ) < minDist )
1088  {
1089  if( track->Type() == PCB_VIA_T )
1090  {
1092  getLocation( track, aTextItem, textSeg ),
1093  track, aTextItem ) );
1094  }
1095  else
1096  {
1098  getLocation( track, aTextItem, textSeg ),
1099  track, aTextItem ) );
1100  }
1101  break;
1102  }
1103  }
1104  }
1105 
1106  // Test pads
1107  for( auto pad : m_pcb->GetPads() )
1108  {
1109  if( !pad->IsOnLayer( aTextItem->GetLayer() ) )
1110  continue;
1111 
1112  // Fast test to detect a pad candidate inside the text bounding box
1113  // Finer test (time consumming) is made only for pads near the text.
1114  int bb_radius = pad->GetBoundingRadius() + pad->GetClearance( NULL );
1115  VECTOR2I shape_pos( pad->ShapePos() );
1116 
1117  if( !rect_area.Collide( SEG( shape_pos, shape_pos ), bb_radius ) )
1118  continue;
1119 
1120  SHAPE_POLY_SET padOutline;
1121 
1122  int minDist = textWidth/2 + pad->GetClearance( NULL );
1123  pad->TransformShapeWithClearanceToPolygon( padOutline, 0 );
1124 
1125  for( unsigned jj = 0; jj < textShape.size(); jj += 2 )
1126  {
1127  SEG textSeg( textShape[jj], textShape[jj+1] );
1128 
1129  if( padOutline.Distance( textSeg, 0 ) <= minDist )
1130  {
1132  pad->GetPosition(), pad, aTextItem ) );
1133  break;
1134  }
1135  }
1136  }
1137 }
int GetX() const
Definition: eda_rect.h:111
int GetWidth() const
Definition: eda_rect.h:119
int GetThickness() const
Return the pen width.
Definition: eda_text.h:148
EDA_UNITS userUnits() const
Definition: drc.h:196
via and copper graphic collide or are too close
Definition: drc.h:77
BOARD * m_pcb
Definition: drc.h:179
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:109
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
#define NULL
SHAPE_POLY_SET.
EDA_RECT GetTextBox(int aLine=-1, int aThickness=-1, bool aInvertY=false, int aMarkupFlags=0) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:184
void TransformTextShapeToSegmentList(std::vector< wxPoint > &aCornerBuffer) const
Convert the text shape to a list of segment.
Definition: eda_text.cpp:544
int GetHeight() const
Definition: eda_rect.h:120
Definition: seg.h:39
const std::vector< D_PAD * > GetPads()
Function GetPads returns a reference to a list of all the pads.
pad and copper graphic collide or are too close
Definition: drc.h:78
track & copper graphic collide or are too close
Definition: drc.h:76
int Distance(VECTOR2I aPoint)
Function DistanceToPolygon computes the minimum distance between aPoint and all the polygons in the s...
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
int GetY() const
Definition: eda_rect.h:112
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
TRACKS & Tracks()
Definition: class_board.h:220
wxPoint getLocation(TRACK *aTrack, ZONE_CONTAINER *aConflictZone) const
Fetches a reasonable point for marking a violoation between two non-point objects.

References addMarkerToPcb(), SHAPE_POLY_SET::Distance(), DRCE_PAD_NEAR_COPPER, DRCE_TRACK_NEAR_COPPER, DRCE_VIA_NEAR_COPPER, EDA_RECT::GetHeight(), BOARD_ITEM::GetLayer(), getLocation(), BOARD::GetPads(), EDA_TEXT::GetTextBox(), EDA_TEXT::GetThickness(), EDA_RECT::GetWidth(), EDA_RECT::GetX(), EDA_RECT::GetY(), m_pcb, NULL, PCB_VIA_T, BOARD::Tracks(), EDA_TEXT::TransformTextShapeToSegmentList(), and userUnits().

Referenced by testCopperTextAndGraphics().

◆ testDisabledLayers()

void DRC::testDisabledLayers ( )
private

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

Definition at line 1154 of file pcbnew/drc/drc.cpp.

1155 {
1157  wxCHECK( board, /*void*/ );
1158  LSET disabledLayers = board->GetEnabledLayers().flip();
1159 
1160  // Perform the test only for copper layers
1161  disabledLayers &= LSET::AllCuMask();
1162 
1163  auto createMarker = [&]( BOARD_ITEM* aItem ) {
1165  aItem->GetPosition(), aItem ) );
1166  };
1167 
1168  for( auto track : board->Tracks() )
1169  {
1170  if( disabledLayers.test( track->GetLayer() ) )
1171  createMarker( track );
1172  }
1173 
1174  for( auto module : board->Modules() )
1175  {
1177  [&]( BOARD_ITEM* aItem )
1178  {
1179  if( disabledLayers.test( aItem->GetLayer() ) )
1180  createMarker( aItem );
1181  } );
1182  }
1183 
1184  for( auto zone : board->Zones() )
1185  {
1186  if( disabledLayers.test( zone->GetLayer() ) )
1187  createMarker( zone );
1188  }
1189 }
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:686
void RunOnChildren(const std::function< void(BOARD_ITEM *)> &aFunction)
Function RunOnChildren.
BOARD * board() const
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
EDA_UNITS userUnits() const
Definition: drc.h:196
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
LSET is a set of PCB_LAYER_IDs.
MODULES & Modules()
Definition: class_board.h:229
item on a disabled layer
Definition: drc.h:86
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
ZONE_CONTAINERS & Zones()
Definition: class_board.h:243
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:163
MODULE * module() const
BOARD * GetBoard() const
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
TRACKS & Tracks()
Definition: class_board.h:220

References addMarkerToPcb(), LSET::AllCuMask(), PCB_TOOL_BASE::board(), DRCE_DISABLED_LAYER_ITEM, PCB_BASE_FRAME::GetBoard(), BOARD::GetEnabledLayers(), BOARD_ITEM::GetLayer(), m_pcbEditorFrame, PCB_TOOL_BASE::module(), BOARD::Modules(), MODULE::RunOnChildren(), BOARD::Tracks(), userUnits(), and BOARD::Zones().

Referenced by RunTests().

◆ testDrilledHoles()

void DRC::testDrilledHoles ( )
private

Definition at line 658 of file pcbnew/drc/drc.cpp.

659 {
660  int holeToHoleMin = m_pcb->GetDesignSettings().m_HoleToHoleMin;
661 
662  if( holeToHoleMin == 0 ) // No min setting turns testing off.
663  return;
664 
665  // Test drilled hole clearances to minimize drill bit breakage.
666  //
667  // Notes: slots are milled, so we're only concerned with circular holes
668  // microvias are laser-drilled, so we're only concerned with standard vias
669 
670  struct DRILLED_HOLE
671  {
672  wxPoint m_location;
673  int m_drillRadius;
674  BOARD_ITEM* m_owner;
675  };
676 
677  std::vector<DRILLED_HOLE> holes;
678  DRILLED_HOLE hole;
679 
680  for( MODULE* mod : m_pcb->Modules() )
681  {
682  for( D_PAD* pad : mod->Pads( ) )
683  {
684  if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
685  {
686  hole.m_location = pad->GetPosition();
687  hole.m_drillRadius = pad->GetDrillSize().x / 2;
688  hole.m_owner = pad;
689  holes.push_back( hole );
690  }
691  }
692  }
693 
694  for( TRACK* track : m_pcb->Tracks() )
695  {
696  VIA* via = dynamic_cast<VIA*>( track );
697  if( via && via->GetViaType() == VIATYPE::THROUGH )
698  {
699  hole.m_location = via->GetPosition();
700  hole.m_drillRadius = via->GetDrillValue() / 2;
701  hole.m_owner = via;
702  holes.push_back( hole );
703  }
704  }
705 
706  for( size_t ii = 0; ii < holes.size(); ++ii )
707  {
708  const DRILLED_HOLE& refHole = holes[ ii ];
709 
710  for( size_t jj = ii + 1; jj < holes.size(); ++jj )
711  {
712  const DRILLED_HOLE& checkHole = holes[ jj ];
713 
714  // Holes with identical locations are allowable
715  if( checkHole.m_location == refHole.m_location )
716  continue;
717 
718  if( KiROUND( GetLineLength( checkHole.m_location, refHole.m_location ) )
719  < checkHole.m_drillRadius + refHole.m_drillRadius + holeToHoleMin )
720  {
722  DRCE_DRILLED_HOLES_TOO_CLOSE, refHole.m_location,
723  refHole.m_owner, refHole.m_location,
724  checkHole.m_owner, checkHole.m_location ) );
725  }
726  }
727  }
728 }
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:206
overlapping drilled holes break drill bits
Definition: drc.h:87
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:229
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
const wxPoint GetPosition() const override
Definition: class_track.h:389
VIATYPE GetViaType() const
Definition: class_track.h:416
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
TRACKS & Tracks()
Definition: class_board.h:220
EDA_UNITS GetUserUnits() const
Return the user units currently in use.

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

Referenced by RunTests().

◆ TestFootprints()

void DRC::TestFootprints ( NETLIST aNetlist,
BOARD aPCB,
EDA_UNITS  aUnits,
std::vector< DRC_ITEM * > &  aDRCList 
)
static

Test the board footprints against a netlist.

Will report DRCE_MISSING_FOOTPRINT, DRCE_DUPLICATE_FOOTPRINT and DRCE_EXTRA_FOOTPRINT errors in aDRCList.

Definition at line 1335 of file pcbnew/drc/drc.cpp.

1337 {
1338 
1339  // Search for duplicate footprints on the board
1340  auto comp = []( const MODULE* x, const MODULE* y )
1341  {
1342  return x->GetReference().CmpNoCase( y->GetReference() ) < 0;
1343  };
1344  auto mods = std::set<MODULE*, decltype( comp )>( comp );
1345 
1346  for( auto mod : aPCB->Modules() )
1347  {
1348  auto ins = mods.insert( mod );
1349 
1350  if( !ins.second )
1351  {
1352  DRC_ITEM* item = new DRC_ITEM();
1353  item->SetData( aUnits, DRCE_DUPLICATE_FOOTPRINT, mod, mod->GetPosition(),
1354  *ins.first, ( *ins.first )->GetPosition() );
1355  aDRCList.push_back( item );
1356  }
1357  }
1358 
1359  // Search for component footprints in the netlist but not on the board.
1360  for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ )
1361  {
1362  COMPONENT* component = aNetlist.GetComponent( ii );
1363 
1364  auto module = aPCB->FindModuleByReference( component->GetReference() );
1365 
1366  if( module == NULL )
1367  {
1368  DRC_ITEM* item = new DRC_ITEM();
1369  item->SetData( DRCE_MISSING_FOOTPRINT, wxString::Format( wxT( "%s (%s)" ),
1370  component->GetReference(),
1371  component->GetValue() ) );
1372  aDRCList.push_back( item );
1373  }
1374  }
1375 
1376  // Search for component footprints found on board but not in netlist.
1377  for( auto module : mods )
1378  {
1379  COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() );
1380 
1381  if( component == NULL )
1382  {
1383  DRC_ITEM* item = new DRC_ITEM();
1384  item->SetData( aUnits, DRCE_EXTRA_FOOTPRINT, module, module->GetPosition() );
1385  aDRCList.push_back( item );
1386  }
1387  }
1388 }
void SetData(EDA_UNITS aUnits, int aErrorCode, EDA_ITEM *aMainItem, EDA_ITEM *bAuxItem=nullptr)
Function SetData initialize all data in item.
Definition: rc_item.h:128
footprint not found for netlist item
Definition: drc.h:90
more than one footprints found for netlist item
Definition: drc.h:91
unsigned GetCount() const
Function GetCount.
Definition: pcb_netlist.h:254
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:436
netlist item not found for footprint
Definition: drc.h:92
#define NULL
MODULES & Modules()
Definition: class_board.h:229
const wxString & GetReference() const
Definition: pcb_netlist.h:149
COMPONENT is used to store components and all of their related information found in a netlist.
Definition: pcb_netlist.h:80
COMPONENT * GetComponent(unsigned aIndex)
Function GetComponent returns the COMPONENT at aIndex.
Definition: pcb_netlist.h:263
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
MODULE * module() const
MODULE * FindModuleByReference(const wxString &aReference) const
Function FindModuleByReference searches for a MODULE within this board with the given reference desig...
const wxString & GetValue() const
Definition: pcb_netlist.h:151
COMPONENT * GetComponentByReference(const wxString &aReference)
Function GetComponentByReference returns a COMPONENT by aReference.
const wxPoint GetPosition() const override
Definition: class_module.h:210

References DRCE_DUPLICATE_FOOTPRINT, DRCE_EXTRA_FOOTPRINT, DRCE_MISSING_FOOTPRINT, BOARD::FindModuleByReference(), Format(), NETLIST::GetComponent(), NETLIST::GetComponentByReference(), NETLIST::GetCount(), MODULE::GetPosition(), COMPONENT::GetReference(), MODULE::GetReference(), COMPONENT::GetValue(), PCB_TOOL_BASE::module(), BOARD::Modules(), NULL, and RC_ITEM::SetData().

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

◆ testKeepoutAreas()

void DRC::testKeepoutAreas ( )
private

Definition at line 844 of file pcbnew/drc/drc.cpp.

845 {
846  // Get a list of all zones to inspect, from both board and footprints
847  std::list<ZONE_CONTAINER*> areasToInspect = m_pcb->GetZoneList( true );
848 
849  // Test keepout areas for vias, tracks and pads inside keepout areas
850  for( ZONE_CONTAINER* area : areasToInspect )
851  {
852 
853  if( !area->GetIsKeepout() )
854  continue;
855 
856  for( auto segm : m_pcb->Tracks() )
857  {
858  if( segm->Type() == PCB_TRACE_T )
859  {
860  if( !area->GetDoNotAllowTracks() )
861  continue;
862 
863  // Ignore if the keepout zone is not on the same layer
864  if( !area->IsOnLayer( segm->GetLayer() ) )
865  continue;
866 
867  SEG trackSeg( segm->GetStart(), segm->GetEnd() );
868 
869  if( area->Outline()->Distance( trackSeg, segm->GetWidth() ) == 0 )
870  {
872  getLocation( segm, area ), segm, area ) );
873  }
874  }
875  else if( segm->Type() == PCB_VIA_T )
876  {
877  if( ! area->GetDoNotAllowVias() )
878  continue;
879 
880  auto viaLayers = segm->GetLayerSet();
881 
882  if( !area->CommonLayerExists( viaLayers ) )
883  continue;
884 
885  if( area->Outline()->Distance( segm->GetPosition() ) < segm->GetWidth()/2 )
886  {
888  getLocation( segm, area ), segm, area ) );
889  }
890  }
891  }
892  // Test pads: TODO
893  }
894 }
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
Via in inside a keepout area.
Definition: drc.h:73
EDA_UNITS userUnits() const
Definition: drc.h:196
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
Definition: seg.h:39
Track in inside a keepout area.
Definition: drc.h:74
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
TRACKS & Tracks()
Definition: class_board.h:220
std::list< ZONE_CONTAINER * > GetZoneList(bool aIncludeZonesInFootprints=false)
Function GetZoneList.
wxPoint getLocation(TRACK *aTrack, ZONE_CONTAINER *aConflictZone) const
Fetches a reasonable point for marking a violoation between two non-point objects.

References addMarkerToPcb(), DRCE_TRACK_INSIDE_KEEPOUT, DRCE_VIA_INSIDE_KEEPOUT, getLocation(), BOARD::GetZoneList(), m_pcb, PCB_TRACE_T, PCB_VIA_T, BOARD::Tracks(), and userUnits().

Referenced by RunTests().

◆ testNetClasses()

bool DRC::testNetClasses ( )
private

Go through each NETCLASS and verifies that its clearance, via size, track width, and track clearance are larger than those in board.m_designSettings.

This is necessary because the actual DRC checks are run against the NETCLASS limits, so in order enforce global limits, we first check the NETCLASSes against the global limits.

Returns
bool - true if succes, else false but only after reporting all NETCLASS violations.

Definition at line 603 of file pcbnew/drc/drc.cpp.

604 {
605  bool ret = true;
607  wxString msg; // construct this only once here, not in a loop, since somewhat expensive.
608 
609  if( !doNetClass( netclasses.GetDefault(), msg ) )
610  ret = false;
611 
612  for( NETCLASSES::const_iterator i = netclasses.begin(); i != netclasses.end(); ++i )
613  {
614  NETCLASSPTR nc = i->second;
615 
616  if( !doNetClass( nc, msg ) )
617  ret = false;
618  }
619 
620  return ret;
621 }
bool doNetClass(const std::shared_ptr< NETCLASS > &aNetClass, wxString &msg)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:512
iterator end()
Definition: netclass.h:249
NETCLASS_MAP::const_iterator const_iterator
Definition: netclass.h:251
BOARD * m_pcb
Definition: drc.h:179
iterator begin()
Definition: netclass.h:248
NETCLASSES is a container for NETCLASS instances.
Definition: netclass.h:224
NETCLASSPTR GetDefault() const
Function GetDefault.
Definition: netclass.h:268

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

Referenced by RunTests().

◆ testOutline()

void DRC::testOutline ( )
private

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

Definition at line 1140 of file pcbnew/drc/drc.cpp.

1141 {
1143 
1145 
1146  if( !m_pcb->GetBoardPolygonOutlines( m_board_outlines, nullptr, &error_loc ) )
1147  {
1149  return;
1150  }
1151 }
const EDA_RECT GetBoardEdgesBoundingBox() const
Function GetBoardEdgesBoundingBox Returns the board bounding box calculated using exclusively the boa...
Definition: class_board.h:767
EDA_UNITS userUnits() const
Definition: drc.h:196
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
const wxPoint GetPosition() const
Definition: eda_rect.h:115
invalid board outline
Definition: drc.h:89
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines,...
SHAPE_POLY_SET m_board_outlines
Definition: drc.h:180
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.

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

Referenced by RunTests().

◆ testPad2Pad()

void DRC::testPad2Pad ( )
private

Definition at line 624 of file pcbnew/drc/drc.cpp.

625 {
626  std::vector<D_PAD*> sortedPads;
627 
628  m_pcb->GetSortedPadListByXthenYCoord( sortedPads );
629 
630  if( sortedPads.empty() )
631  return;
632 
633  // find the max size of the pads (used to stop the test)
634  int max_size = 0;
635 
636  for( D_PAD* pad : sortedPads )
637  {
638  // GetBoundingRadius() is the radius of the minimum sized circle fully containing the pad
639  int radius = pad->GetBoundingRadius();
640 
641  if( radius > max_size )
642  max_size = radius;
643  }
644 
645  // Upper limit of pad list (limit not included)
646  D_PAD** listEnd = &sortedPads[0] + sortedPads.size();
647 
648  // Test the pads
649  for( auto& pad : sortedPads )
650  {
651  int x_limit = pad->GetClearance() + pad->GetBoundingRadius() + pad->GetPosition().x;
652 
653  doPadToPadsDrc( pad, &pad, listEnd, max_size + x_limit );
654  }
655 }
void GetSortedPadListByXthenYCoord(std::vector< D_PAD * > &aVector, int aNetCode=-1)
Function GetSortedPadListByXthenYCoord first empties then fills the vector with all pads and sorts th...
BOARD * m_pcb
Definition: drc.h:179
bool doPadToPadsDrc(D_PAD *aRefPad, D_PAD **aStart, D_PAD **aEnd, int x_limit)
Test the clearance between aRefPad and other pads.
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:596

References doPadToPadsDrc(), D_PAD::GetClearance(), BOARD::GetSortedPadListByXthenYCoord(), and m_pcb.

Referenced by RunTests().

◆ testTracks()

void DRC::testTracks ( wxWindow *  aActiveWindow,
bool  aShowProgressBar 
)
private

Perform the DRC on all tracks.

This test can take a while, a progress bar can be displayed

Parameters
aActiveWindow= the active window ued as parent for the progress bar
aShowProgressBar= true to show a progress bar (Note: it is shown only if there are many tracks)

Definition at line 731 of file pcbnew/drc/drc.cpp.

732 {
733  wxProgressDialog * progressDialog = NULL;
734  const int delta = 500; // This is the number of tests between 2 calls to the
735  // progress bar
736  int count = m_pcb->Tracks().size();
737 
738  int deltamax = count/delta;
739 
740  if( aShowProgressBar && deltamax > 3 )
741  {
742  // Do not use wxPD_APP_MODAL style here: it is not necessary and create issues
743  // on OSX
744  progressDialog = new wxProgressDialog( _( "Track clearances" ), wxEmptyString,
745  deltamax, aActiveWindow,
746  wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME );
747  progressDialog->Update( 0, wxEmptyString );
748  }
749 
750  int ii = 0;
751  count = 0;
752 
753  for( auto seg_it = m_pcb->Tracks().begin(); seg_it != m_pcb->Tracks().end(); seg_it++ )
754  {
755  if( ii++ > delta )
756  {
757  ii = 0;
758  count++;
759 
760  if( progressDialog )
761  {
762  if( !progressDialog->Update( count, wxEmptyString ) )
763  break; // Aborted by user
764 #ifdef __WXMAC__
765  // Work around a dialog z-order issue on OS X
766  if( count == deltamax )
767  aActiveWindow->Raise();
768 #endif
769  }
770  }
771 
772  // Test new segment against tracks and pads, optionally against copper zones
773  doTrackDrc( *seg_it, seg_it + 1, m_pcb->Tracks().end(), m_doZonesTest );
774  }
775 
776  if( progressDialog )
777  progressDialog->Destroy();
778 }
BOARD * m_pcb
Definition: drc.h:179
bool m_doZonesTest
Definition: drc.h:149
#define NULL
#define _(s)
Definition: 3d_actions.cpp:33
void doTrackDrc(TRACK *aRefSeg, TRACKS::iterator aStartIt, TRACKS::iterator aEndIt, bool aTestZones)
Test the current segment.
TRACKS & Tracks()
Definition: class_board.h:220

References _, doTrackDrc(), m_doZonesTest, m_pcb, NULL, and BOARD::Tracks().

Referenced by RunTests().

◆ testUnconnected()

void DRC::testUnconnected ( )
private

Definition at line 781 of file pcbnew/drc/drc.cpp.

782 {
783  for( DRC_ITEM* unconnectedItem : m_unconnected )
784  delete unconnectedItem;
785 
786  m_unconnected.clear();
787 
788  auto connectivity = m_pcb->GetConnectivity();
789 
790  connectivity->Clear();
791  connectivity->Build( m_pcb ); // just in case. This really needs to be reliable.
792  connectivity->RecalculateRatsnest();
793 
794  std::vector<CN_EDGE> edges;
795  connectivity->GetUnconnectedEdges( edges );
796 
797  for( const auto& edge : edges )
798  {
799  DRC_ITEM* item = new DRC_ITEM();
801  edge.GetSourceNode()->Parent(), (wxPoint) edge.GetSourcePos(),
802  edge.GetTargetNode()->Parent(), (wxPoint) edge.GetTargetPos() );
803  m_unconnected.push_back( item );
804  }
805 }
void SetData(EDA_UNITS aUnits, int aErrorCode, EDA_ITEM *aMainItem, EDA_ITEM *bAuxItem=nullptr)
Function SetData initialize all data in item.
Definition: rc_item.h:128
BOARD * m_pcb
Definition: drc.h:179
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:306
std::vector< DRC_ITEM * > m_unconnected
Definition: drc.h:183
PCB_EDIT_FRAME * m_pcbEditorFrame
Definition: drc.h:178
items are unconnected
Definition: drc.h:45
EDA_UNITS GetUserUnits() const
Return the user units currently in use.

References DRCE_UNCONNECTED_ITEMS, BOARD::GetConnectivity(), EDA_BASE_FRAME::GetUserUnits(), m_pcb, m_pcbEditorFrame, m_unconnected, and RC_ITEM::SetData().

Referenced by RunTests().

◆ testZones()

void DRC::testZones ( )
private

Definition at line 808 of file pcbnew/drc/drc.cpp.

809 {
810  // Test copper areas for valid netcodes
811  // if a netcode is < 0 the netname was not found when reading a netlist
812  // if a netcode is == 0 the netname is void, and the zone is not connected.
813  // This is allowed, but i am not sure this is a good idea
814  //
815  // In recent Pcbnew versions, the netcode is always >= 0, but an internal net name
816  // is stored, and initialized from the file or the zone properties editor.
817  // if it differs from the net name from net code, there is a DRC issue
818  for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
819  {
820  ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
821 
822  if( !zone->IsOnCopperLayer() )
823  continue;
824 
825  int netcode = zone->GetNetCode();
826  // a netcode < 0 or > 0 and no pad in net is a error or strange
827  // perhaps a "dead" net, which happens when all pads in this net were removed
828  // Remark: a netcode < 0 should not happen (this is more a bug somewhere)
829  int pads_in_net = ( netcode > 0 ) ? m_pcb->GetConnectivity()->GetPadCount( netcode ) : 1;
830 
831  if( ( netcode < 0 ) || pads_in_net == 0 )
832  {
833  wxPoint markerPos = zone->GetPosition();
835  markerPos, zone ) );
836  }
837  }
838 
839  // Test copper areas outlines, and create markers when needed
841 }
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
int GetNetCode() const
Function GetNetCode.
copper area has a net but no pads in nets, which is suspicious
Definition: drc.h:59
EDA_UNITS userUnits() const
Definition: drc.h:196
const wxPoint GetPosition() const override
Definition: class_zone.cpp:207
BOARD * m_pcb
Definition: drc.h:179
void addMarkerToPcb(MARKER_PCB *aMarker)
Adds a DRC marker to the PCB through the COMMIT mechanism.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:919
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:306
int TestZoneToZoneOutlines()
Tests whether distance between zones complies with the DRC rules.
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:884
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:219

References addMarkerToPcb(), DRCE_SUSPICIOUS_NET_FOR_ZONE_OUTLINE, BOARD::GetArea(), BOARD::GetAreaCount(), BOARD::GetConnectivity(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPosition(), ZONE_CONTAINER::IsOnCopperLayer(), m_pcb, TestZoneToZoneOutlines(), and userUnits().

Referenced by RunTests().

◆ TestZoneToZoneOutlines()

int DRC::TestZoneToZoneOutlines ( )

Tests whether distance between zones complies with the DRC rules.

Returns
Errors count

Definition at line 179 of file pcbnew/drc/drc.cpp.

180 {
182  int nerrors = 0;
183 
184  std::vector<SHAPE_POLY_SET> smoothed_polys;
185  smoothed_polys.resize( board->GetAreaCount() );
186 
187  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
188  {
189  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
190  std::set<VECTOR2I> colinearCorners;
191  zoneRef->GetColinearCorners( board, colinearCorners );
192 
193  zoneRef->BuildSmoothedPoly( smoothed_polys[ia], &colinearCorners );
194  }
195 
196  // iterate through all areas
197  for( int ia = 0; ia < board->GetAreaCount(); ia++ )
198  {
199  ZONE_CONTAINER* zoneRef = board->GetArea( ia );
200 
201  if( !zoneRef->IsOnCopperLayer() )
202  continue;
203 
204  // If we are testing a single zone, then iterate through all other zones
205  // Otherwise, we have already tested the zone combination
206  for( int ia2 = ia + 1; ia2 < board->GetAreaCount(); ia2++ )
207  {
208  ZONE_CONTAINER* zoneToTest = board->GetArea( ia2 );
209 
210  if( zoneRef == zoneToTest )
211  continue;
212 
213  // test for same layer
214  if( zoneRef->GetLayer() != zoneToTest->GetLayer() )
215  continue;
216 
217  // Test for same net
218  if( zoneRef->GetNetCode() == zoneToTest->GetNetCode() && zoneRef->GetNetCode() >= 0 )
219  continue;
220 
221  // test for different priorities
222  if( zoneRef->GetPriority() != zoneToTest->GetPriority() )
223  continue;
224 
225  // test for different types
226  if( zoneRef->GetIsKeepout() != zoneToTest->GetIsKeepout() )
227  continue;
228 
229  // Examine a candidate zone: compare zoneToTest to zoneRef
230 
231  // Get clearance used in zone to zone test. The policy used to
232  // obtain that value is now part of the zone object itself by way of
233  // ZONE_CONTAINER::GetClearance().
234  int zone2zoneClearance = zoneRef->GetClearance( zoneToTest );
235 
236  // Keepout areas have no clearance, so set zone2zoneClearance to 1
237  // ( zone2zoneClearance = 0 can create problems in test functions)
238  if( zoneRef->GetIsKeepout() )
239  zone2zoneClearance = 1;
240 
241  // test for some corners of zoneRef inside zoneToTest
242  for( auto iterator = smoothed_polys[ia].IterateWithHoles(); iterator; iterator++ )
243  {
244  VECTOR2I currentVertex = *iterator;
245  wxPoint pt( currentVertex.x, currentVertex.y );
246 
247  if( smoothed_polys[ia2].Contains( currentVertex ) )
248  {
250  zoneRef, zoneToTest ) );
251  nerrors++;
252  }
253  }
254 
255  // test for some corners of zoneToTest inside zoneRef
256  for( auto iterator = smoothed_polys[ia2].IterateWithHoles(); iterator; iterator++ )
257  {
258  VECTOR2I currentVertex = *iterator;
259  wxPoint pt( currentVertex.x, currentVertex.y );
260 
261  if( smoothed_polys[ia].Contains( currentVertex ) )
262  {
264  zoneToTest, zoneRef ) );
265  nerrors++;
266  }
267  }
268 
269  // Iterate through all the segments of refSmoothedPoly
270  std::set<wxPoint> conflictPoints;
271 
272  for( auto refIt = smoothed_polys[ia].IterateSegmentsWithHoles(); refIt; refIt++ )
273  {
274  // Build ref segment
275  SEG refSegment = *refIt;
276 
277  // Iterate through all the segments in smoothed_polys[ia2]
278  for( auto testIt = smoothed_polys[ia2].IterateSegmentsWithHoles(); testIt; testIt++ )
279  {
280  // Build test segment
281  SEG testSegment = *testIt;
282  wxPoint pt;
283 
284  int ax1, ay1, ax2, ay2;
285  ax1 = refSegment.A.x;
286  ay1 = refSegment.A.y;
287