First draft of courtyard overlap detection.
This commit is contained in:
parent
f7632d5473
commit
b365f17e9f
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
@ -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();
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue