Encourage use of full DRC for board & footprint malformed outlines.
It shows much more detail. Removes some nag dialogs and places hypertext links in others. Also fixes the auto-layer-showing to correctly show Edge.Cuts or F.CrtYd or B.CrtYd for errors relating to them. Fixes https://gitlab.com/kicad/code/kicad/issues/6446
This commit is contained in:
parent
0a7ef25453
commit
b123318cf6
|
@ -461,27 +461,26 @@ bool BOARD_ADAPTER::createBoardPolygon( wxString* aErrorMsg )
|
|||
{
|
||||
m_board_poly.RemoveAllContours();
|
||||
|
||||
bool success = false;
|
||||
wxString msg;
|
||||
bool success;
|
||||
|
||||
if( m_board->IsFootprintHolder() )
|
||||
{
|
||||
success = BuildFootprintPolygonOutlines( m_board, m_board_poly,
|
||||
m_board->GetDesignSettings().m_MaxError, &msg );
|
||||
m_board->GetDesignSettings().m_MaxError, nullptr );
|
||||
|
||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||
m_board_poly.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
||||
if( aErrorMsg )
|
||||
*aErrorMsg = msg;
|
||||
if( !success && aErrorMsg )
|
||||
*aErrorMsg = _( "Footprint outline is malformed. Run DRC for a full analysis." );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
success = m_board->GetBoardPolygonOutlines( m_board_poly, &msg );
|
||||
success = m_board->GetBoardPolygonOutlines( m_board_poly );
|
||||
|
||||
if( aErrorMsg )
|
||||
*aErrorMsg = _( "Board outline is not closed:" ) + wxS( " " )+ msg;
|
||||
if( !success && aErrorMsg )
|
||||
*aErrorMsg = _( "Board outline is malformed. Run DRC for a full analysis." );
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
@ -119,8 +119,9 @@ typedef const INSPECTOR_FUNC& INSPECTOR; /// std::function passed to nested u
|
|||
#define IS_PASTED (1 << 17) ///< Modifier on IS_NEW which indicates it came from clipboard
|
||||
#define TRACK_LOCKED (1 << 18) ///< Pcbnew: track locked: protected from global deletion
|
||||
#define TRACK_AR (1 << 19) ///< Pcbnew: autorouted track
|
||||
#define OBSOLETE_1 (1 << 20) ///< Not presently used
|
||||
#define MALFORMED_COURTYARD (1 << 21)
|
||||
#define MALFORMED_F_COURTYARD (1 << 20)
|
||||
#define MALFORMED_B_COURTYARD (1 << 21)
|
||||
#define MALFORMED_COURTYARDS ( MALFORMED_F_COURTYARD | MALFORMED_B_COURTYARD )
|
||||
#define BEGIN_ONPAD (1 << 22) ///< Pcbnew: flag set for track segment starting on a pad
|
||||
#define END_ONPAD (1 << 23) ///< Pcbnew: flag set for track segment ending on a pad
|
||||
#define HOLE_PROXY (1 << 24) ///< Indicates the BOARD_ITEM is a proxy for its hole
|
||||
|
|
|
@ -113,7 +113,7 @@ int AR_AUTOPLACER::genPlacementRoutingMatrix()
|
|||
return 0;
|
||||
|
||||
// Build the board shape
|
||||
m_board->GetBoardPolygonOutlines( m_boardShape /*, aErrorText, aErrorLocation*/ );
|
||||
m_board->GetBoardPolygonOutlines( m_boardShape );
|
||||
m_topFreeArea = m_boardShape;
|
||||
m_bottomFreeArea = m_boardShape;
|
||||
|
||||
|
|
|
@ -1842,12 +1842,12 @@ bool BOARD::NormalizeAreaPolygon( PICKED_ITEMS_LIST * aNewZonesList, ZONE* aCurr
|
|||
}
|
||||
|
||||
|
||||
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText,
|
||||
bool BOARD::GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
||||
std::vector<wxPoint>* aDiscontinuities,
|
||||
std::vector<wxPoint>* aIntersections )
|
||||
{
|
||||
bool success = BuildBoardPolygonOutlines( this, aOutlines, GetDesignSettings().m_MaxError,
|
||||
aErrorText, aDiscontinuities, aIntersections );
|
||||
aDiscontinuities, aIntersections );
|
||||
|
||||
// Make polygon strictly simple to avoid issues (especially in 3D viewer)
|
||||
aOutlines.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
|
||||
|
|
|
@ -588,8 +588,6 @@ public:
|
|||
* Any closed outline inside the main outline is a hole
|
||||
* All contours should be closed, i.e. have valid vertices to build a closed polygon
|
||||
* @param aOutlines The SHAPE_POLY_SET to fill in with outlines/holes.
|
||||
* @param aErrorText = an optional wxString for an error message with the coordinate of the
|
||||
* first discontinuity or self-intersection
|
||||
* @param aDiscontinuities = an optional array of wxPoint giving the locations of
|
||||
* discontinuities in the outline
|
||||
* @param aIntersections = an optional array of wxPoint giving the locations of self-
|
||||
|
@ -597,7 +595,7 @@ public:
|
|||
*
|
||||
* @return true if success, false if a contour is not valid
|
||||
*/
|
||||
bool GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines, wxString* aErrorText = nullptr,
|
||||
bool GetBoardPolygonOutlines( SHAPE_POLY_SET& aOutlines,
|
||||
std::vector<wxPoint>* aDiscontinuities = nullptr,
|
||||
std::vector<wxPoint>* aIntersections = nullptr );
|
||||
|
||||
|
|
|
@ -191,17 +191,14 @@ static PCB_SHAPE* findNext( PCB_SHAPE* aShape, const wxPoint& aPoint,
|
|||
* These closed inner outlines are considered as holes in the main outline
|
||||
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
|
||||
* @param aPolygons will contain the complex polygon.
|
||||
* @param aTolerance is the max distance between points that is still accepted as connected
|
||||
* (internal units)
|
||||
* @param aErrorText is a wxString to return error message.
|
||||
* @param aTolerance is the max error distance when polygonizing a curve (internal units)
|
||||
* @param aDiscontinuities = an optional array of wxPoint giving the locations of
|
||||
* discontinuities in the outline
|
||||
* @param aIntersections = an optional array of wxPoint giving the locations of self-
|
||||
* intersections in the outline
|
||||
*/
|
||||
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
||||
unsigned int aTolerance, wxString* aErrorText,
|
||||
std::vector<wxPoint>* aDiscontinuities,
|
||||
int aTolerance, std::vector<wxPoint>* aDiscontinuities,
|
||||
std::vector<wxPoint>* aIntersections )
|
||||
{
|
||||
if( aSegList.size() == 0 )
|
||||
|
@ -519,15 +516,6 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
}
|
||||
else // encountered discontinuity
|
||||
{
|
||||
if( aErrorText )
|
||||
{
|
||||
msg.Printf( _( "Unable to find edge with an endpoint of (%s, %s)." ),
|
||||
StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.x ),
|
||||
StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.y ) );
|
||||
|
||||
*aErrorText << msg << "\n";
|
||||
}
|
||||
|
||||
if( aDiscontinuities )
|
||||
aDiscontinuities->emplace_back( prevPt );
|
||||
|
||||
|
@ -731,15 +719,6 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
}
|
||||
else // encountered discontinuity
|
||||
{
|
||||
if( aErrorText )
|
||||
{
|
||||
msg.Printf( _( "Unable to find edge with an endpoint of (%s, %s)." ),
|
||||
StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.x ),
|
||||
StringFromValue( EDA_UNITS::MILLIMETRES, prevPt.y ) );
|
||||
|
||||
*aErrorText << msg << "\n";
|
||||
}
|
||||
|
||||
if( aDiscontinuities )
|
||||
aDiscontinuities->emplace_back( prevPt );
|
||||
|
||||
|
@ -795,8 +774,8 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
* Any closed outline inside the main outline is a hole
|
||||
* All contours should be closed, i.e. valid closed polygon vertices
|
||||
*/
|
||||
bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, unsigned int aTolerance,
|
||||
wxString* aErrorText, std::vector<wxPoint>* aDiscontinuities,
|
||||
bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
||||
std::vector<wxPoint>* aDiscontinuities,
|
||||
std::vector<wxPoint>* aIntersections )
|
||||
{
|
||||
PCB_TYPE_COLLECTOR items;
|
||||
|
@ -817,12 +796,8 @@ bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, unsign
|
|||
|
||||
if( segList.size() )
|
||||
{
|
||||
success = ConvertOutlineToPolygon( segList, aOutlines, aTolerance, aErrorText,
|
||||
aDiscontinuities, aIntersections );
|
||||
}
|
||||
else if( aErrorText )
|
||||
{
|
||||
*aErrorText = _( "No edges found on Edge.Cuts layer." );
|
||||
success = ConvertOutlineToPolygon( segList, aOutlines, aTolerance, aDiscontinuities,
|
||||
aIntersections );
|
||||
}
|
||||
|
||||
if( !success || !aOutlines.OutlineCount() )
|
||||
|
@ -1035,8 +1010,8 @@ bool BuildFootprintPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
|
|||
segList.push_back( static_cast<PCB_SHAPE*>( items[ii] ) );
|
||||
}
|
||||
|
||||
bool success = ConvertOutlineToPolygon( segList, outlines, aTolerance, aErrorText,
|
||||
aDiscontinuities, aIntersections );
|
||||
bool success = ConvertOutlineToPolygon( segList, outlines, aTolerance, aDiscontinuities,
|
||||
aIntersections );
|
||||
|
||||
FOOTPRINT* footprint = aBoard->GetFirstFootprint();
|
||||
|
||||
|
|
|
@ -41,17 +41,14 @@ class wxPoint;
|
|||
* These closed inner outlines are considered as holes in the main outline
|
||||
* @param aSegList the initial list of drawsegments (only lines, circles and arcs).
|
||||
* @param aPolygons will contain the complex polygon.
|
||||
* @param aTolerance is the max distance between points that is still accepted as connected
|
||||
* (internal units)
|
||||
* @param aErrorText is a wxString to return error message.
|
||||
* @param aTolerance is the max error distance when polygonizing a curve (internal units)
|
||||
* @param aDiscontinuities = an optional array of wxPoint giving the locations of
|
||||
* discontinuities in the outline
|
||||
* @param aIntersections = an optional array of wxPoint giving the locations of self-
|
||||
* intersections in the outline
|
||||
*/
|
||||
bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET& aPolygons,
|
||||
unsigned int aTolerance, wxString* aErrorText,
|
||||
std::vector<wxPoint>* aDiscontinuities = nullptr,
|
||||
int aTolerance, std::vector<wxPoint>* aDiscontinuities = nullptr,
|
||||
std::vector<wxPoint>* aIntersections = nullptr );
|
||||
|
||||
|
||||
|
@ -62,8 +59,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
|
|||
* All contours should be closed, i.e. are valid vertices for a closed polygon
|
||||
* return true if success, false if a contour is not valid
|
||||
*/
|
||||
extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines,
|
||||
unsigned int aTolerance, wxString* aErrorText,
|
||||
extern bool BuildBoardPolygonOutlines( BOARD* aBoard, SHAPE_POLY_SET& aOutlines, int aTolerance,
|
||||
std::vector<wxPoint>* aDiscontinuities = nullptr,
|
||||
std::vector<wxPoint>* aIntersections = nullptr );
|
||||
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
#include <dialog_constraints_reporter.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <wx_html_report_box.h>
|
||||
|
||||
#include <tools/pcb_actions.h>
|
||||
|
||||
DIALOG_CONSTRAINTS_REPORTER::DIALOG_CONSTRAINTS_REPORTER( PCB_EDIT_FRAME* aParent ) :
|
||||
DIALOG_CONSTRAINTS_REPORTER_BASE( aParent ),
|
||||
|
@ -47,7 +48,10 @@ void DIALOG_CONSTRAINTS_REPORTER::DeleteAllPages()
|
|||
|
||||
void DIALOG_CONSTRAINTS_REPORTER::OnErrorLinkClicked( wxHtmlLinkEvent& event )
|
||||
{
|
||||
m_frame->ShowBoardSetupDialog( _( "Rules" ) );
|
||||
if( event.GetLinkInfo().GetHref() == "boardsetup" )
|
||||
m_frame->ShowBoardSetupDialog( _( "Rules" ) );
|
||||
else if( event.GetLinkInfo().GetHref() == "drc" )
|
||||
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::runDRC, true );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -306,26 +306,46 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
|
|||
if( item && node )
|
||||
{
|
||||
PCB_LAYER_ID principalLayer = item->GetLayer();
|
||||
std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
|
||||
LSET violationLayers;
|
||||
std::shared_ptr<RC_ITEM> rc_item = node->m_RcItem;
|
||||
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
|
||||
BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
|
||||
BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
|
||||
if( rc_item->GetErrorCode() == DRCE_MALFORMED_COURTYARD )
|
||||
{
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
|
||||
LSET violationLayers;
|
||||
if( a && ( a->GetFlags() & MALFORMED_B_COURTYARD ) > 0
|
||||
&& ( a->GetFlags() & MALFORMED_F_COURTYARD ) == 0 )
|
||||
{
|
||||
principalLayer = B_CrtYd;
|
||||
}
|
||||
else
|
||||
{
|
||||
principalLayer = F_CrtYd;
|
||||
}
|
||||
}
|
||||
else if (rc_item->GetErrorCode() == DRCE_INVALID_OUTLINE )
|
||||
{
|
||||
principalLayer = Edge_Cuts;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOARD_ITEM* a = board->GetItem( rc_item->GetMainItemID() );
|
||||
BOARD_ITEM* b = board->GetItem( rc_item->GetAuxItemID() );
|
||||
BOARD_ITEM* c = board->GetItem( rc_item->GetAuxItem2ID() );
|
||||
BOARD_ITEM* d = board->GetItem( rc_item->GetAuxItem3ID() );
|
||||
|
||||
if( a )
|
||||
violationLayers &= a->GetLayerSet();
|
||||
if( a )
|
||||
violationLayers &= a->GetLayerSet();
|
||||
|
||||
if( b )
|
||||
violationLayers &= b->GetLayerSet();
|
||||
if( b )
|
||||
violationLayers &= b->GetLayerSet();
|
||||
|
||||
if( c )
|
||||
violationLayers &= c->GetLayerSet();
|
||||
if( c )
|
||||
violationLayers &= c->GetLayerSet();
|
||||
|
||||
if( d )
|
||||
violationLayers &= d->GetLayerSet();
|
||||
if( d )
|
||||
violationLayers &= d->GetLayerSet();
|
||||
}
|
||||
|
||||
if( violationLayers.count() )
|
||||
principalLayer = violationLayers.Seq().front();
|
||||
|
@ -339,7 +359,7 @@ void DIALOG_DRC::OnDRCItemSelected( wxDataViewEvent& aEvent )
|
|||
|
||||
if( ( violationLayers & board->GetVisibleLayers() ) == 0 )
|
||||
{
|
||||
m_brdEditor->GetAppearancePanel()->SetLayerVisible( item->GetLayer(), true );
|
||||
m_brdEditor->GetAppearancePanel()->SetLayerVisible( principalLayer, true );
|
||||
m_brdEditor->GetCanvas()->Refresh();
|
||||
}
|
||||
|
||||
|
|
|
@ -205,8 +205,8 @@ void PCB_EDIT_FRAME::OnExportSTEP( wxCommandEvent& event )
|
|||
{
|
||||
if( !doAutoSave() )
|
||||
{
|
||||
DisplayErrorMessage( this,
|
||||
_( "STEP export failed! Please save the PCB and try again" ) );
|
||||
DisplayErrorMessage( this, _( "STEP export failed! "
|
||||
"Please save the PCB and try again" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -245,9 +245,9 @@ void DIALOG_EXPORT_STEP::onExportButton( wxCommandEvent& aEvent )
|
|||
wxString msg;
|
||||
|
||||
// Check if the board outline is continuous
|
||||
if( !BuildBoardPolygonOutlines( m_parent->GetBoard(), outline, Millimeter2iu( 0.01 ), &msg ) )
|
||||
if( !BuildBoardPolygonOutlines( m_parent->GetBoard(), outline, Millimeter2iu( 0.01 ) ) )
|
||||
{
|
||||
DisplayErrorMessage( this, _( "Cannot determine the board outline." ), msg );
|
||||
DisplayErrorMessage( this, _( "Board outline is malformed. Run DRC for a full analysis." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,18 +87,40 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
|||
if( !reportProgress( ii++, m_board->Footprints().size(), delta ) )
|
||||
return;
|
||||
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARD ) != 0 )
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
|
||||
{
|
||||
if( m_drcEngine->IsErrorLimitExceeded( DRCE_MALFORMED_COURTYARD) )
|
||||
continue;
|
||||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD );
|
||||
std::vector<wxPoint> discontinuities;
|
||||
std::vector<wxPoint> intersections;
|
||||
|
||||
m_msg.Printf( drcItem->GetErrorText() + wxS( " " ) + _( "(not a closed shape)" ) );
|
||||
// Run courtyard test again to get error locations
|
||||
footprint->BuildPolyCourtyards( &discontinuities, &intersections);
|
||||
|
||||
drcItem->SetErrorMessage( m_msg );
|
||||
drcItem->SetItems( footprint );
|
||||
reportViolation( drcItem, footprint->GetPosition());
|
||||
for( wxPoint pt : discontinuities )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD );
|
||||
|
||||
m_msg.Printf( _( "(not a closed shape)" ) );
|
||||
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( footprint );
|
||||
|
||||
reportViolation( drcItem, pt );
|
||||
}
|
||||
|
||||
for( wxPoint pt : intersections )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD );
|
||||
|
||||
m_msg.Printf( _( "(self-intersecting)" ) );
|
||||
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( footprint );
|
||||
|
||||
reportViolation( drcItem, pt );
|
||||
}
|
||||
}
|
||||
else if( footprint->GetPolyCourtyardFront().OutlineCount() == 0
|
||||
&& footprint->GetPolyCourtyardBack().OutlineCount() == 0 )
|
||||
|
@ -108,7 +130,7 @@ void DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions()
|
|||
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD );
|
||||
drcItem->SetItems( footprint );
|
||||
reportViolation( drcItem, footprint->GetPosition());
|
||||
reportViolation( drcItem, footprint->GetPosition() );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -85,34 +85,43 @@ void DRC_TEST_PROVIDER_MISC::testOutline()
|
|||
|
||||
SHAPE_POLY_SET boardOutlines;
|
||||
|
||||
if( m_board->GetBoardPolygonOutlines( boardOutlines, nullptr, &discontinuities,
|
||||
&intersections ) )
|
||||
if(! m_board->GetBoardPolygonOutlines( boardOutlines, &discontinuities, &intersections ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( boardOutlines.IsEmpty() )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
|
||||
for( wxPoint pt : discontinuities )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
m_msg.Printf( _( "(no edges found on Edge.Cuts layer)" ) );
|
||||
|
||||
m_msg.Printf( _( "(not a closed shape)" ) );
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( m_board );
|
||||
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( m_board );
|
||||
reportViolation( drcItem, m_board->GetBoundingBox().Centre() );
|
||||
}
|
||||
|
||||
reportViolation( drcItem, pt );
|
||||
}
|
||||
for( wxPoint pt : discontinuities )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
|
||||
for( wxPoint pt : intersections )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
m_msg.Printf( _( "(not a closed shape)" ) );
|
||||
|
||||
m_msg.Printf( _( "(self-intersecting)" ) );
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( m_board );
|
||||
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( m_board );
|
||||
reportViolation( drcItem, pt );
|
||||
}
|
||||
|
||||
reportViolation( drcItem, pt );
|
||||
for( wxPoint pt : intersections )
|
||||
{
|
||||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE );
|
||||
|
||||
m_msg.Printf( _( "(self-intersecting)" ) );
|
||||
|
||||
drcItem->SetErrorMessage( drcItem->GetErrorText() + wxS( " " ) + m_msg );
|
||||
drcItem->SetItems( m_board );
|
||||
|
||||
reportViolation( drcItem, pt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -299,6 +299,7 @@ bool HYPERLYNX_EXPORTER::writeBoardInfo()
|
|||
|
||||
if( !m_board->GetBoardPolygonOutlines( outlines ) )
|
||||
{
|
||||
wxLogError( _( "Board outline is malformed. Run DRC for a full analysis." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -829,13 +829,10 @@ static void export_vrml_drawings( MODEL_VRML& aModel, BOARD* pcb )
|
|||
static void export_vrml_board( MODEL_VRML& aModel, BOARD* aPcb )
|
||||
{
|
||||
SHAPE_POLY_SET pcbOutlines; // stores the board main outlines
|
||||
wxString msg;
|
||||
|
||||
if( !aPcb->GetBoardPolygonOutlines( pcbOutlines, &msg ) )
|
||||
if( !aPcb->GetBoardPolygonOutlines( pcbOutlines ) )
|
||||
{
|
||||
msg << "\n\n" <<
|
||||
_( "Unable to calculate the board outlines; fall back to using the board boundary box." );
|
||||
wxMessageBox( msg );
|
||||
wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
|
||||
}
|
||||
|
||||
int seg;
|
||||
|
@ -864,18 +861,14 @@ static void export_vrml_board( MODEL_VRML& aModel, BOARD* aPcb )
|
|||
|
||||
if( seg < 0 )
|
||||
{
|
||||
msg << "\n\n" <<
|
||||
_( "VRML Export Failed: Could not add holes to contours." );
|
||||
wxMessageBox( msg );
|
||||
|
||||
wxLogError( _( "VRML Export Failed: Could not add holes to contours." ) );
|
||||
return;
|
||||
}
|
||||
|
||||
for( int j = 0; j < hole.PointCount(); j++ )
|
||||
{
|
||||
aModel.m_holes.AddVertex( seg, (double)hole.CPoint(j).x * BOARD_SCALE,
|
||||
-((double)hole.CPoint(j).y * BOARD_SCALE ) );
|
||||
|
||||
aModel.m_holes.AddVertex( seg, (double) hole.CPoint(j).x * BOARD_SCALE,
|
||||
-( (double) hole.CPoint(j).y * BOARD_SCALE ) );
|
||||
}
|
||||
|
||||
aModel.m_holes.EnsureWinding( seg, true );
|
||||
|
|
|
@ -173,16 +173,18 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, PCB_LAYER
|
|||
// We plot the footprint courtyard when possible.
|
||||
// If not, the pads bounding box will be used.
|
||||
bool useFpPadsBbox = true;
|
||||
bool onBack = aLayer == B_Cu;
|
||||
|
||||
footprint->BuildPolyCourtyards();
|
||||
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARD ) == 0 )
|
||||
int checkFlag = onBack ? MALFORMED_B_COURTYARD : MALFORMED_F_COURTYARD;
|
||||
|
||||
if( ( footprint->GetFlags() & checkFlag ) == 0 )
|
||||
{
|
||||
gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CMP_COURTYARD );
|
||||
|
||||
SHAPE_POLY_SET& courtyard = aLayer == B_Cu ?
|
||||
footprint->GetPolyCourtyardBack():
|
||||
footprint->GetPolyCourtyardFront();
|
||||
SHAPE_POLY_SET& courtyard = onBack ? footprint->GetPolyCourtyardBack()
|
||||
: footprint->GetPolyCourtyardFront();
|
||||
|
||||
for( int ii = 0; ii < courtyard.OutlineCount(); ii++ )
|
||||
{
|
||||
|
|
|
@ -1693,11 +1693,12 @@ std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
|
|||
}
|
||||
|
||||
|
||||
void FOOTPRINT::BuildPolyCourtyards()
|
||||
void FOOTPRINT::BuildPolyCourtyards( std::vector<wxPoint>* aDiscontinuities,
|
||||
std::vector<wxPoint>* aIntersections )
|
||||
{
|
||||
m_poly_courtyard_front.RemoveAllContours();
|
||||
m_poly_courtyard_back.RemoveAllContours();
|
||||
ClearFlags( MALFORMED_COURTYARD );
|
||||
ClearFlags( MALFORMED_COURTYARDS );
|
||||
|
||||
// Build the courtyard area from graphic items on the courtyard.
|
||||
// Only PCB_FP_SHAPE_T have meaning, graphic texts are ignored.
|
||||
|
@ -1717,26 +1718,18 @@ void FOOTPRINT::BuildPolyCourtyards()
|
|||
if( !list_front.size() && !list_back.size() )
|
||||
return;
|
||||
|
||||
wxString error_msg;
|
||||
|
||||
#define ARC_ERROR_MAX 0.02 /* error max in mm to approximate a arc by segments */
|
||||
if( !ConvertOutlineToPolygon( list_front, m_poly_courtyard_front,
|
||||
(unsigned) Millimeter2iu( ARC_ERROR_MAX ), &error_msg ) )
|
||||
|
||||
if( !ConvertOutlineToPolygon( list_front, m_poly_courtyard_front, Millimeter2iu( ARC_ERROR_MAX ),
|
||||
aDiscontinuities, aIntersections ) )
|
||||
{
|
||||
SetFlags( MALFORMED_COURTYARD );
|
||||
SetFlags( MALFORMED_F_COURTYARD );
|
||||
}
|
||||
|
||||
if( !ConvertOutlineToPolygon( list_back, m_poly_courtyard_back,
|
||||
(unsigned) Millimeter2iu( ARC_ERROR_MAX ), &error_msg ) )
|
||||
if( !ConvertOutlineToPolygon( list_back, m_poly_courtyard_back, Millimeter2iu( ARC_ERROR_MAX ),
|
||||
aDiscontinuities, aIntersections ) )
|
||||
{
|
||||
SetFlags( MALFORMED_COURTYARD );
|
||||
}
|
||||
|
||||
if( !error_msg.IsEmpty() )
|
||||
{
|
||||
wxLogMessage( wxString::Format( _( "Processing courtyard of \"%s\": %s" ),
|
||||
GetFPID().Format().wx_str(),
|
||||
error_msg ) );
|
||||
SetFlags( MALFORMED_B_COURTYARD );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -666,10 +666,11 @@ public:
|
|||
|
||||
/**
|
||||
* Builds complex polygons of the courtyard areas from graphic items on the courtyard layers
|
||||
* @remark sets the MALFORMED_FRONT_COURTYARD and MALFORMED_BACK_COURTYARD status flags if
|
||||
* the given courtyard layer does not contain a (single) closed shape
|
||||
* @remark sets the MALFORMED_F_COURTYARD and MALFORMED_B_COURTYARD status flags if the given
|
||||
* courtyard layer does not contain a (single) closed shape
|
||||
*/
|
||||
void BuildPolyCourtyards();
|
||||
void BuildPolyCourtyards( std::vector<wxPoint>* aDiscontinuities = nullptr,
|
||||
std::vector<wxPoint>* aIntersections = nullptr );
|
||||
|
||||
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ static void insideArea( LIBEVAL::CONTEXT* aCtx, void* self )
|
|||
{
|
||||
FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
|
||||
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARD ) != 0 )
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
|
||||
{
|
||||
aCtx->ReportError( _( "Footprint's courtyard is not a single, closed shape." ) );
|
||||
return false;
|
||||
|
|
|
@ -831,10 +831,12 @@ PADSTACK* SPECCTRA_DB::makeVia( const ::VIA* aVia )
|
|||
|
||||
void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary )
|
||||
{
|
||||
wxString errMessage;
|
||||
SHAPE_POLY_SET outlines;
|
||||
|
||||
aBoard->GetBoardPolygonOutlines( outlines, &errMessage );
|
||||
if( !aBoard->GetBoardPolygonOutlines( outlines ) )
|
||||
{
|
||||
wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
|
||||
}
|
||||
|
||||
for( int cnt = 0; cnt < outlines.OutlineCount(); cnt++ ) // Should be one outline
|
||||
{
|
||||
|
@ -878,9 +880,6 @@ void SPECCTRA_DB::fillBOUNDARY( BOARD* aBoard, BOUNDARY* boundary )
|
|||
poly_ko->AppendPoint( mapPt( pos ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( !errMessage.IsEmpty() )
|
||||
wxLogMessage( errMessage );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@
|
|||
|
||||
void DIALOG_INSPECTION_REPORTER::OnErrorLinkClicked( wxHtmlLinkEvent& event )
|
||||
{
|
||||
m_frame->ShowBoardSetupDialog( _( "Rules" ) );
|
||||
if( event.GetLinkInfo().GetHref() == "boardsetup" )
|
||||
m_frame->ShowBoardSetupDialog( _( "Rules" ) );
|
||||
else if( event.GetLinkInfo().GetHref() == "drc" )
|
||||
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::runDRC, true );
|
||||
}
|
||||
|
||||
|
||||
|
@ -399,6 +402,7 @@ int PCB_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
|
|||
|
||||
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
|
||||
DRC_ENGINE drcEngine( m_frame->GetBoard(), &m_frame->GetBoard()->GetDesignSettings() );
|
||||
bool courtyardError = false;
|
||||
bool compileError = false;
|
||||
|
||||
try
|
||||
|
@ -419,6 +423,9 @@ int PCB_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
|
|||
zone->CacheBoundingBox();
|
||||
|
||||
footprint->BuildPolyCourtyards();
|
||||
|
||||
if( ( footprint->GetFlags() & MALFORMED_COURTYARDS ) != 0 )
|
||||
courtyardError = true;
|
||||
}
|
||||
|
||||
if( item->Type() == PCB_TRACE_T )
|
||||
|
@ -575,6 +582,13 @@ int PCB_INSPECTION_TOOL::InspectConstraints( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else
|
||||
{
|
||||
if( courtyardError )
|
||||
{
|
||||
r->Report( "" );
|
||||
r->Report( _( "Report may be incomplete: some footprint courtyards are malformed. " )
|
||||
+ "<a href='drc'>" + _( "Run DRC for a full analysis." ) + "</a>" );
|
||||
}
|
||||
|
||||
auto constraint = drcEngine.EvalRulesForItems( DISALLOW_CONSTRAINT, item, nullptr,
|
||||
UNDEFINED_LAYER, r );
|
||||
|
||||
|
|
Loading…
Reference in New Issue