First draft of courtyard overlap detection.

This commit is contained in:
jean-pierre charras 2017-03-16 18:09:33 +01:00
parent f7632d5473
commit b365f17e9f
12 changed files with 1562 additions and 889 deletions

View File

@ -126,6 +126,12 @@ wxString DRC_ITEM::GetErrorText() const
case DRCE_PAD_INSIDE_TEXT:
return wxString( _( "Pad inside a text" ) );
case DRCE_OVERLAPPING_FOOTPRINTS:
return wxString( _( "Courtyards overlap" ) );
case DRCE_MISSING_COURTYARD_IN_FOOTPRINT:
return wxString( _( "Footprint has no courtard defined" ) );
default:
return wxString::Format( wxT( "Unknown DRC error code %d" ), m_ErrorCode );
}

View File

@ -48,6 +48,7 @@
#include <class_board.h>
#include <class_edge_mod.h>
#include <class_module.h>
#include <convert_basic_shapes_to_polygon.h>
#include <view/view.h>
@ -1219,3 +1220,76 @@ double MODULE::PadCoverageRatio() const
return std::min( ratio, 1.0 );
}
bool MODULE::BuildPolyCourtyard()
{
m_poly_courtyard.RemoveAllContours();
// Build the courtyard area from graphic items on the courtyard.
// Only PCB_MODULE_EDGE_T have meaning, graphic texts are ignored.
// Collect items:
std::vector< EDGE_MODULE* > list;
for( BOARD_ITEM* item = GraphicalItems(); item; item = item->Next() )
{
if( item->GetLayer() == B_CrtYd && item->Type() == PCB_MODULE_EDGE_T )
list.push_back( static_cast< EDGE_MODULE* > ( item ) );
if( item->GetLayer() == F_CrtYd && item->Type() == PCB_MODULE_EDGE_T )
list.push_back( static_cast< EDGE_MODULE* > ( item ) );
}
if( !list.size() )
return false;
// Build the coutyard
const int circleToSegmentsCount = 16;
EDA_RECT rect; // the bouding box of segments
bool has_segments = false;
for( EDGE_MODULE* item : list )
{
switch( item->GetShape() )
{
case S_SEGMENT:
if( !has_segments )
{
rect.Move( item->GetStart() );
has_segments = true;
}
else
rect.Merge( item->GetStart() );
rect.Merge( item->GetEnd() );
break;
case S_CIRCLE:
TransformCircleToPolygon( m_poly_courtyard, item->GetCenter(),
item->GetRadius(), circleToSegmentsCount );
break;
case S_ARC:
break;
case S_POLYGON:
break;
default:
break;
}
}
if( has_segments ) // Build the polygon from bounding box
{
m_poly_courtyard.NewOutline();
m_poly_courtyard.Append( rect.GetOrigin().x, rect.GetOrigin().y );
m_poly_courtyard.Append( rect.GetOrigin().x + rect.GetWidth(),
rect.GetOrigin().y );
m_poly_courtyard.Append( rect.GetOrigin().x + rect.GetWidth(),
rect.GetOrigin().y + rect.GetHeight() );
m_poly_courtyard.Append( rect.GetOrigin().x,
rect.GetOrigin().y + rect.GetHeight() );
}
return true;
}

View File

@ -640,6 +640,19 @@ public:
/// Return the initial comments block or NULL if none, without transfer of ownership.
const wxArrayString* GetInitialComments() const { return m_initial_comments; }
/** Used in DRC to test the courtyard area (a complex polygon)
* @return the courtyard polygon
*/
SHAPE_POLY_SET& GetPolyCourtyard() { return m_poly_courtyard; }
/** Used in DRC to build the courtyard area (a complex polygon)
* from graphic items put on the courtyard
* @return true if OK, false if the polygon cannot be built
* The polygon cannot be built if segments/arcs on courtyard layers
* cannot be grouped in a polygon.
*/
bool BuildPolyCourtyard();
#if defined(DEBUG)
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
#endif
@ -682,6 +695,9 @@ private:
wxArrayString* m_initial_comments; ///< leading s-expression comments in the module,
///< lazily allocated only if needed for speed
/// Used in DRC to test the courtyard area (a polygon which can be not basic
SHAPE_POLY_SET m_poly_courtyard;
};
#endif // MODULE_H_

View File

@ -1,8 +1,8 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View File

@ -5,9 +5,9 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2009-2016 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2004-2016 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2017 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -28,6 +28,7 @@
*/
#include <fctsys.h>
#include <kiface_i.h>
#include <confirm.h>
#include <wildcards_and_files_ext.h>
#include <pgm_base.h>
@ -42,10 +43,16 @@
* and run DRC tests
*/
// Keywords for read and write config
#define TestMissingCourtyardKey wxT( "TestMissingCourtyard" )
#define TestFootprintCourtyardKey wxT( "TestFootprintCourtyard" )
DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFrame,
wxWindow* aParent ) :
DIALOG_DRC_CONTROL_BASE( aParent )
{
m_config = Kiface().KifaceSettings();
m_tester = aTester;
m_brdEditor = aEditorFrame;
m_currentBoard = m_brdEditor->GetBoard();
@ -57,6 +64,11 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFra
FinishDialogSettings();
}
DIALOG_DRC_CONTROL::~DIALOG_DRC_CONTROL()
{
m_config->Write( TestMissingCourtyardKey, m_cbCourtyardMissing->GetValue() );
m_config->Write( TestFootprintCourtyardKey, m_cbCourtyardOverlap->GetValue() );
}
void DIALOG_DRC_CONTROL::OnActivateDlg( wxActivateEvent& event )
{
@ -111,6 +123,14 @@ void DIALOG_DRC_CONTROL::InitValues()
DisplayDRCValues();
// read options
bool value;
m_config->Read( TestMissingCourtyardKey, &value, false );
m_cbCourtyardMissing->SetValue( value );
m_config->Read( TestFootprintCourtyardKey, &value, false );
m_cbCourtyardOverlap->SetValue( value );
// Set the initial "enabled" status of the browse button and the text
// field for report name
wxCommandEvent junk;
@ -172,6 +192,8 @@ void DIALOG_DRC_CONTROL::OnStartdrcClick( wxCommandEvent& event )
true, // unconnected pads DRC test enabled
true, // DRC test for zones enabled
true, // DRC test for keepout areas enabled
m_cbCourtyardOverlap->GetValue(),
m_cbCourtyardMissing->GetValue(),
reportName, make_report );
DelDRCMarkers();
@ -243,6 +265,8 @@ void DIALOG_DRC_CONTROL::OnListUnconnectedClick( wxCommandEvent& event )
true, // unconnected pads DRC test enabled
true, // DRC test for zones enabled
true, // DRC test for keepout areas enabled
m_cbCourtyardOverlap->GetValue(),
m_cbCourtyardMissing->GetValue(),
reportName, make_report );
DelDRCMarkers();

View File

@ -58,7 +58,7 @@ public:
/// Constructors
DIALOG_DRC_CONTROL( DRC* aTester, PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent );
~DIALOG_DRC_CONTROL(){};
~DIALOG_DRC_CONTROL();
/**
* Enable/disable the report file creation
@ -147,6 +147,7 @@ private:
BOARD* m_currentBoard; // the board currently on test
DRC* m_tester;
PCB_EDIT_FRAME* m_brdEditor;
wxConfigBase* m_config;
};
#endif // _DIALOG_DRC_H_

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Feb 16 2016)
// C++ code generated with wxFormBuilder (version May 6 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@ -21,11 +21,23 @@ DIALOG_DRC_CONTROL_BASE::DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID i
wxBoxSizer* m_CommandSizer;
m_CommandSizer = new wxBoxSizer( wxHORIZONTAL );
wxStaticBoxSizer* sbSizerOptions;
sbSizerOptions = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Options:") ), wxHORIZONTAL );
wxBoxSizer* bSizerOptions;
bSizerOptions = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizer7;
bSizer7 = new wxBoxSizer( wxVERTICAL );
m_staticTextOptions = new wxStaticText( this, wxID_ANY, _("Options:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextOptions->Wrap( -1 );
m_staticTextOptions->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
bSizerOptions->Add( m_staticTextOptions, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerOptsSettings;
bSizerOptsSettings = new wxBoxSizer( wxHORIZONTAL );
bSizerOptsSettings->Add( 20, 20, 0, 0, 5 );
wxBoxSizer* bSizerOptSettings;
bSizerOptSettings = new wxBoxSizer( wxVERTICAL );
wxFlexGridSizer* fgMinValuesSizer;
fgMinValuesSizer = new wxFlexGridSizer( 4, 3, 0, 0 );
@ -33,91 +45,121 @@ DIALOG_DRC_CONTROL_BASE::DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID i
fgMinValuesSizer->SetFlexibleDirection( wxHORIZONTAL );
fgMinValuesSizer->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_ClearanceTitle = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Clearance"), wxDefaultPosition, wxDefaultSize, 0 );
m_ClearanceTitle = new wxStaticText( this, wxID_ANY, _("Clearance"), wxDefaultPosition, wxDefaultSize, 0 );
m_ClearanceTitle->Wrap( -1 );
fgMinValuesSizer->Add( m_ClearanceTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
fgMinValuesSizer->Add( m_ClearanceTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_SetClearance = new wxTextCtrl( sbSizerOptions->GetStaticBox(), wxID_ANY, _("By Netclass"), wxDefaultPosition, wxDefaultSize, 0 );
m_SetClearance = new wxTextCtrl( this, wxID_ANY, _("By Netclass"), wxDefaultPosition, wxDefaultSize, 0 );
m_SetClearance->Enable( false );
fgMinValuesSizer->Add( m_SetClearance, 0, wxALL|wxEXPAND, 5 );
fgMinValuesSizer->Add( m_SetClearance, 0, wxEXPAND|wxALL, 5 );
fgMinValuesSizer->Add( 0, 0, 1, wxEXPAND, 5 );
fgMinValuesSizer->Add( 0, 0, 0, 0, 5 );
m_TrackMinWidthTitle = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Min track width"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthTitle = new wxStaticText( this, wxID_ANY, _("Min track width"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthTitle->Wrap( -1 );
m_TrackMinWidthTitle->SetToolTip( _("Enter the minimum acceptable value for a track width") );
fgMinValuesSizer->Add( m_TrackMinWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
fgMinValuesSizer->Add( m_TrackMinWidthTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_SetTrackMinWidthCtrl = new wxTextCtrl( sbSizerOptions->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetTrackMinWidthCtrl, 0, wxALL|wxEXPAND, 5 );
m_SetTrackMinWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetTrackMinWidthCtrl, 0, wxEXPAND|wxALL, 5 );
m_TrackMinWidthUnit = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_TrackMinWidthUnit->Wrap( -1 );
m_TrackMinWidthUnit->SetToolTip( _("Enter the minimum acceptable value for a track width") );
fgMinValuesSizer->Add( m_TrackMinWidthUnit, 0, wxALL, 5 );
fgMinValuesSizer->Add( m_TrackMinWidthUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_ViaMinTitle = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Min via size"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinTitle = new wxStaticText( this, wxID_ANY, _("Min via size"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinTitle->Wrap( -1 );
m_ViaMinTitle->SetHelpText( _("Enter the minimum acceptable diameter for a standard via") );
fgMinValuesSizer->Add( m_ViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
fgMinValuesSizer->Add( m_ViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_SetViaMinSizeCtrl = new wxTextCtrl( sbSizerOptions->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_SetViaMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetViaMinSizeCtrl, 0, wxALL|wxEXPAND, 5 );
m_ViaMinUnit = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_ViaMinUnit->Wrap( -1 );
m_ViaMinUnit->SetHelpText( _("Enter the minimum acceptable diameter for a standard via") );
fgMinValuesSizer->Add( m_ViaMinUnit, 0, wxALL, 5 );
fgMinValuesSizer->Add( m_ViaMinUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
m_MicroViaMinTitle = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Min uVia size"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinTitle = new wxStaticText( this, wxID_ANY, _("Min uVia size"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinTitle->Wrap( -1 );
m_MicroViaMinTitle->SetToolTip( _("Enter the minimum acceptable diameter for a micro via") );
fgMinValuesSizer->Add( m_MicroViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxALL, 5 );
fgMinValuesSizer->Add( m_MicroViaMinTitle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT|wxLEFT, 5 );
m_SetMicroViakMinSizeCtrl = new wxTextCtrl( sbSizerOptions->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_SetMicroViakMinSizeCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
fgMinValuesSizer->Add( m_SetMicroViakMinSizeCtrl, 0, wxALL|wxEXPAND, 5 );
m_MicroViaMinUnit = new wxStaticText( sbSizerOptions->GetStaticBox(), wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinUnit = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
m_MicroViaMinUnit->Wrap( -1 );
m_MicroViaMinUnit->SetToolTip( _("Enter the minimum acceptable diameter for a micro via") );
fgMinValuesSizer->Add( m_MicroViaMinUnit, 0, wxALL, 5 );
fgMinValuesSizer->Add( m_MicroViaMinUnit, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bSizer7->Add( fgMinValuesSizer, 1, wxEXPAND, 5 );
bSizerOptSettings->Add( fgMinValuesSizer, 0, wxEXPAND, 5 );
wxStaticBoxSizer* ReportFileSizer;
ReportFileSizer = new wxStaticBoxSizer( new wxStaticBox( sbSizerOptions->GetStaticBox(), wxID_ANY, _("Create Report File") ), wxHORIZONTAL );
m_cbCourtyardOverlap = new wxCheckBox( this, wxID_ANY, _("Check footprint courtyard overlap"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerOptSettings->Add( m_cbCourtyardOverlap, 0, wxALL, 5 );
m_CreateRptCtrl = new wxCheckBox( ReportFileSizer->GetStaticBox(), ID_CHECKBOX_RPT_FILE, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_cbCourtyardMissing = new wxCheckBox( this, wxID_ANY, _("Check courtyard missing in footprints"), wxDefaultPosition, wxDefaultSize, 0 );
bSizerOptSettings->Add( m_cbCourtyardMissing, 0, wxBOTTOM|wxRIGHT|wxLEFT, 5 );
bSizerOptsSettings->Add( bSizerOptSettings, 1, wxEXPAND, 5 );
bSizerOptions->Add( bSizerOptsSettings, 1, wxEXPAND, 5 );
bSizerOptions->Add( 10, 5, 0, 0, 5 );
m_staticTextRpt = new wxStaticText( this, wxID_ANY, _("Create Report File"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticTextRpt->Wrap( -1 );
m_staticTextRpt->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
bSizerOptions->Add( m_staticTextRpt, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
wxBoxSizer* bSizerRpt;
bSizerRpt = new wxBoxSizer( wxHORIZONTAL );
bSizerRpt->Add( 20, 20, 0, 0, 5 );
wxFlexGridSizer* fgSizerRpt;
fgSizerRpt = new wxFlexGridSizer( 0, 3, 0, 0 );
fgSizerRpt->AddGrowableCol( 1 );
fgSizerRpt->SetFlexibleDirection( wxBOTH );
fgSizerRpt->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_CreateRptCtrl = new wxCheckBox( this, ID_CHECKBOX_RPT_FILE, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_CreateRptCtrl->SetToolTip( _("Enable writing report to this file") );
ReportFileSizer->Add( m_CreateRptCtrl, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 );
fgSizerRpt->Add( m_CreateRptCtrl, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
m_RptFilenameCtrl = new wxTextCtrl( ReportFileSizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_RptFilenameCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_RptFilenameCtrl->SetToolTip( _("Enter the report filename") );
m_RptFilenameCtrl->SetMinSize( wxSize( 180,-1 ) );
ReportFileSizer->Add( m_RptFilenameCtrl, 1, wxALL|wxEXPAND, 5 );
fgSizerRpt->Add( m_RptFilenameCtrl, 0, wxEXPAND|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_BrowseButton = new wxButton( ReportFileSizer->GetStaticBox(), ID_BUTTON_BROWSE_RPT_FILE, _("..."), wxDefaultPosition, wxSize( 50,-1 ), 0 );
ReportFileSizer->Add( m_BrowseButton, 0, wxALIGN_CENTER_VERTICAL, 5 );
m_BrowseButton = new wxButton( this, ID_BUTTON_BROWSE_RPT_FILE, _("..."), wxDefaultPosition, wxSize( 50,-1 ), 0 );
fgSizerRpt->Add( m_BrowseButton, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
bSizer7->Add( ReportFileSizer, 0, wxEXPAND|wxTOP|wxBOTTOM|wxRIGHT, 5 );
bSizerRpt->Add( fgSizerRpt, 1, 0, 5 );
sbSizerOptions->Add( bSizer7, 1, wxEXPAND, 5 );
bSizerOptions->Add( bSizerRpt, 0, wxEXPAND, 5 );
m_CommandSizer->Add( sbSizerOptions, 1, 0, 5 );
m_CommandSizer->Add( bSizerOptions, 1, wxEXPAND, 5 );
wxBoxSizer* bSizerMessages;
bSizerMessages = new wxBoxSizer( wxVERTICAL );

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Feb 16 2016)
// C++ code generated with wxFormBuilder (version May 6 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@ -25,7 +25,6 @@ class DRCLISTBOX;
#include <wx/sizer.h>
#include <wx/checkbox.h>
#include <wx/button.h>
#include <wx/statbox.h>
#include <wx/statline.h>
#include <wx/listbox.h>
#include <wx/panel.h>
@ -33,6 +32,7 @@ class DRCLISTBOX;
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/notebook.h>
#include <wx/statbox.h>
#include <wx/dialog.h>
///////////////////////////////////////////////////////////////////////////
@ -55,6 +55,7 @@ class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
wxPanel* m_panelUnconnectedBox;
protected:
wxStaticText* m_staticTextOptions;
wxStaticText* m_ClearanceTitle;
wxStaticText* m_TrackMinWidthTitle;
wxStaticText* m_TrackMinWidthUnit;
@ -62,6 +63,9 @@ class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
wxStaticText* m_ViaMinUnit;
wxStaticText* m_MicroViaMinTitle;
wxStaticText* m_MicroViaMinUnit;
wxCheckBox* m_cbCourtyardOverlap;
wxCheckBox* m_cbCourtyardMissing;
wxStaticText* m_staticTextRpt;
wxCheckBox* m_CreateRptCtrl;
wxTextCtrl* m_RptFilenameCtrl;
wxButton* m_BrowseButton;
@ -109,7 +113,7 @@ class DIALOG_DRC_CONTROL_BASE : public DIALOG_SHIM
DRCLISTBOX* m_ClearanceListBox;
DRCLISTBOX* m_UnconnectedListBox;
DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DRC Control"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 733,438 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
DIALOG_DRC_CONTROL_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DRC Control"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 679,518 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
~DIALOG_DRC_CONTROL_BASE();
};

View File

@ -2,9 +2,9 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2016 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2017 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -122,6 +122,8 @@ DRC::DRC( PCB_EDIT_FRAME* aPcbWindow )
m_doUnconnectedTest = true; // enable unconnected tests
m_doZonesTest = true; // enable zone to items clearance tests
m_doKeepoutTest = true; // enable keepout areas to items clearance tests
m_doFootprintOverlapping = true; // enable courtyards areas overlap tests
m_doNoCourtyardDefined = true; // enable missing courtyard in footprint warning
m_abortDRC = false;
m_drcInProgress = false;
@ -298,6 +300,18 @@ void DRC::RunTests( wxTextCtrl* aMessages )
testTexts();
// find overlaping courtyard ares.
if( m_doFootprintOverlapping || m_doNoCourtyardDefined )
{
if( aMessages )
{
aMessages->AppendText( _( "Courtyard areas...\n" ) );
aMessages->Refresh();
}
doFootprintOverlappingDrc();
}
// update the m_drcDialog listboxes
updatePointers();
@ -968,3 +982,70 @@ bool DRC::doPadToPadsDrc( D_PAD* aRefPad, D_PAD** aStart, D_PAD** aEnd, int x_li
return true;
}
bool DRC::doFootprintOverlappingDrc()
{
// Detects missing footprint courtyards, and for others, courtyard overlap.
wxString msg;
bool success = true;
// Update courtyard polygons, and test for missing courtyard definition:
for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
{
footprint->BuildPolyCourtyard();
if( footprint->GetPolyCourtyard().OutlineCount() == 0 && m_doNoCourtyardDefined )
{
msg.Printf( _( "footprint '%s' has no courtyard defined" ),
footprint->GetReference().GetData() );
m_currentMarker = fillMarker( footprint->GetPosition(),
DRCE_MISSING_COURTYARD_IN_FOOTPRINT,
msg, m_currentMarker );
addMarkerToPcb( m_currentMarker );
m_currentMarker = nullptr;
success = false;
}
}
if( !m_doFootprintOverlapping )
return success;
// Now test for overlapping:
for( MODULE* footprint = m_pcb->m_Modules; footprint; footprint = footprint->Next() )
{
if( footprint->GetPolyCourtyard().OutlineCount() == 0 )
continue; // No courtyard defined
for( MODULE* candidate = footprint->Next(); candidate; candidate = candidate->Next() )
{
if( candidate->GetPolyCourtyard().OutlineCount() == 0 )
continue; // No courtyard defined
SHAPE_POLY_SET courtyard;
courtyard.Append( footprint->GetPolyCourtyard() );
// Build the common area between footprint and the candidate:
courtyard.BooleanIntersection( candidate->GetPolyCourtyard(), SHAPE_POLY_SET::PM_FAST );
// If no overlap, courtyard is empty (no common area).
// Therefore if a common polygon exists, this is a DRC error
if( courtyard.OutlineCount() )
{
//Overlap between footprint and candidate
msg.Printf( _( "footprints '%s' and '%s' overlap" ),
footprint->GetReference().GetData(),
candidate->GetReference().GetData() );
VECTOR2I& pos = courtyard.Vertex( 0, 0 );
wxPoint loc( pos.x, pos.y );
m_currentMarker = fillMarker( loc, DRCE_OVERLAPPING_FOOTPRINTS, msg, m_currentMarker );
addMarkerToPcb( m_currentMarker );
m_currentMarker = nullptr;
success = false;
}
}
}
return success;
}

View File

@ -6,8 +6,8 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2010 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2004-2010 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
* Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2004-2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2017 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -224,3 +224,16 @@ MARKER_PCB* DRC::fillMarker( int aErrorCode, const wxString& aMessage, MARKER_PC
return fillMe;
}
MARKER_PCB* DRC::fillMarker( const wxPoint& aPos, int aErrorCode, const wxString& aMessage, MARKER_PCB* fillMe )
{
wxPoint posA = aPos;
if( fillMe )
fillMe->SetData( aErrorCode, posA, aMessage, posA );
else
fillMe = new MARKER_PCB( aErrorCode, posA, aMessage, posA );
return fillMe;
}

View File

@ -6,7 +6,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2016 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors.
* Copyright (C) 2017 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -80,6 +80,8 @@
#define DRCE_VIA_INSIDE_TEXT 41 ///< Via in inside a text area
#define DRCE_TRACK_INSIDE_TEXT 42 ///< Track in inside a text area
#define DRCE_PAD_INSIDE_TEXT 43 ///< Pad in inside a text area
#define DRCE_OVERLAPPING_FOOTPRINTS 44 ///< footprint courtyards overlap
#define DRCE_MISSING_COURTYARD_IN_FOOTPRINT 45 ///< footprint has no courtyard defined
class EDA_DRAW_PANEL;
@ -164,6 +166,8 @@ private:
bool m_doZonesTest;
bool m_doKeepoutTest;
bool m_doCreateRptFile;
bool m_doFootprintOverlapping;
bool m_doNoCourtyardDefined;
wxString m_rptFilename;
@ -230,6 +234,9 @@ private:
MARKER_PCB* fillMarker( ZONE_CONTAINER* aArea, int aErrorCode, MARKER_PCB* fillMe );
MARKER_PCB* fillMarker( const wxPoint& aPos, int aErrorCode,
const wxString& aMessage, MARKER_PCB* fillMe );
/**
* Function fillMarker
* optionally creates a marker and fills it in with information,
@ -341,6 +348,13 @@ private:
*/
bool doEdgeZoneDrc( ZONE_CONTAINER* aArea, int aCornerIndex );
/**
* Function doFootprintOverlappingDrc
* tests for footprint courtyard overlaps
* @return bool - false if DRC error or true if OK
*/
bool doFootprintOverlappingDrc();
//-----<single tests>----------------------------------------------
/**
@ -476,19 +490,24 @@ public:
* @param aUnconnectedTest Tells whether to list unconnected pads.
* @param aZonesTest Tells whether to test zones.
* @param aKeepoutTest Tells whether to test keepout areas.
* @param aCourtyardTest Tells whether to test footprint courtyard overlap.
* @param aCourtyardMissingTest Tells whether to test missing courtyard definition in footprint.
* @param aReportName A string telling the disk file report name entered.
* @param aSaveReport A boolean telling whether to generate disk file report.
*/
void SetSettings( bool aPad2PadTest, bool aUnconnectedTest,
bool aZonesTest, bool aKeepoutTest,
bool aCourtyardTest, bool aCourtyardMissingTest,
const wxString& aReportName, bool aSaveReport )
{
m_doPad2PadTest = aPad2PadTest;
m_doUnconnectedTest = aUnconnectedTest;
m_doZonesTest = aZonesTest;
m_doKeepoutTest = aKeepoutTest;
m_rptFilename = aReportName;
m_doCreateRptFile = aSaveReport;
m_doPad2PadTest = aPad2PadTest;
m_doUnconnectedTest = aUnconnectedTest;
m_doZonesTest = aZonesTest;
m_doKeepoutTest = aKeepoutTest;
m_rptFilename = aReportName;
m_doCreateRptFile = aSaveReport;
m_doFootprintOverlapping = aCourtyardTest;
m_doNoCourtyardDefined = aCourtyardMissingTest;
}