21 changed files with 1743 additions and 214 deletions
-
8qa/drc_proto/CMakeLists.txt
-
53qa/drc_proto/drc_engine.cpp
-
37qa/drc_proto/drc_engine.h
-
10qa/drc_proto/drc_item.cpp
-
2qa/drc_proto/drc_item.h
-
3qa/drc_proto/drc_proto_test.cpp
-
20qa/drc_proto/drc_rtree.h
-
7qa/drc_proto/drc_rule.h
-
153qa/drc_proto/drc_test_provider.cpp
-
8qa/drc_proto/drc_test_provider.h
-
160qa/drc_proto/drc_test_provider_annulus.cpp
-
177qa/drc_proto/drc_test_provider_connectivity.cpp
-
3qa/drc_proto/drc_test_provider_copper_clearance.cpp
-
229qa/drc_proto/drc_test_provider_courtyard_clearance.cpp
-
130qa/drc_proto/drc_test_provider_disallow.cpp
-
31qa/drc_proto/drc_test_provider_edge_clearance.cpp
-
214qa/drc_proto/drc_test_provider_lvs.cpp
-
216qa/drc_proto/drc_test_provider_misc.cpp
-
168qa/drc_proto/drc_test_provider_silk_to_pad.cpp
-
174qa/drc_proto/drc_test_provider_track_width.cpp
-
154qa/drc_proto/drc_test_provider_via_diameter.cpp
@ -0,0 +1,160 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
#include <class_via.h>
|
|||
#include <class_pad.h>
|
|||
|
|||
#include <common.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
|
|||
/*
|
|||
Via/pad annular ring width test. Checks if there's sufficient copper ring around PTH/NPTH holes (vias/pads) |
|||
Errors generated: |
|||
- DRCE_ANNULUS |
|||
|
|||
Todo: |
|||
- check pad holes too. |
|||
- pad stack support (different IAR/OAR values depending on layer) |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_ANNULUS : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_ANNULUS() |
|||
{ |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_ANNULUS() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "annulus"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests pad/via annular rings"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_ANNULUS::Run() |
|||
{ |
|||
if( !m_drcEngine->HasCorrectRulesForId( |
|||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH ) ) |
|||
{ |
|||
ReportAux( "No annulus constraints found. Skipping check." ); |
|||
return false; |
|||
} |
|||
|
|||
ReportStage( ( "Testing via annular rings" ), 0, 2 ); |
|||
|
|||
auto checkAnnulus = [&]( BOARD_ITEM* item ) -> bool |
|||
{ |
|||
bool fail_min = false, fail_max = false; |
|||
int v_min, v_max; |
|||
auto via = dyn_cast<VIA*>( item ); |
|||
|
|||
// fixme: check minimum IAR/OAR ring for THT pads too
|
|||
if( !via ) |
|||
return true; |
|||
|
|||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( |
|||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH, via ); |
|||
|
|||
int annulus = ( via->GetWidth() - via->GetDrillValue() ) / 2; |
|||
|
|||
if( constraint.Value().HasMin() ) |
|||
{ |
|||
v_min = constraint.Value().Min(); |
|||
fail_min = annulus < v_min; |
|||
} |
|||
|
|||
if( constraint.Value().HasMax() ) |
|||
{ |
|||
v_max = constraint.Value().Max(); |
|||
fail_max = annulus > v_max; |
|||
} |
|||
|
|||
if( fail_min || fail_max ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ANNULUS ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (%s; actual annulus %s, constraint %s %s)" ), |
|||
constraint.GetParentRule()->GetName(), |
|||
MessageTextFromValue( userUnits(), annulus, true ), |
|||
fail_min ? _( "minimum" ) : _( "maximum" ), |
|||
MessageTextFromValue( userUnits(), fail_min ? v_min : v_max, true ) ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( item ); |
|||
drcItem->SetViolatingRule( constraint.GetParentRule() ); |
|||
|
|||
ReportWithMarker( drcItem, via->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_ANNULUS ) ) |
|||
return false; |
|||
|
|||
} |
|||
|
|||
return true; |
|||
}; |
|||
|
|||
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkAnnulus ); |
|||
|
|||
reportRuleStatistics(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> |
|||
test::DRC_TEST_PROVIDER_ANNULUS::GetMatchingConstraintIds() const |
|||
{ |
|||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_ANNULUS_WIDTH }; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_ANNULUS> dummy; |
|||
} |
|||
@ -0,0 +1,177 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <connectivity/connectivity_data.h>
|
|||
#include <connectivity/connectivity_algo.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
|
|||
/*
|
|||
Connectivity test provider. Not rule-driven. |
|||
Errors generated: |
|||
- DRCE_DANGLING_TRACK |
|||
- DRCE_DANGLING_VIA |
|||
- DRCE_ZONE_HAS_EMPTY_NET |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_CONNECTIVITY : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_CONNECTIVITY() |
|||
{ |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_CONNECTIVITY() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "connectivity"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests board connectivity"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_CONNECTIVITY::Run() |
|||
{ |
|||
ReportStage( ( "Testing dangling pads/vias" ), 0, 2 ); |
|||
|
|||
BOARD* board = m_drcEngine->GetBoard(); |
|||
|
|||
std::shared_ptr<CONNECTIVITY_DATA> connectivity = board->GetConnectivity(); |
|||
connectivity->Clear(); |
|||
connectivity->Build( board ); // just in case. This really needs to be reliable.
|
|||
|
|||
|
|||
for( auto track : board->Tracks() ) |
|||
{ |
|||
bool exceedT = isErrorLimitExceeded( DRCE_DANGLING_TRACK ); |
|||
bool exceedV = isErrorLimitExceeded( DRCE_DANGLING_VIA ); |
|||
// Test for dangling items
|
|||
int code = track->Type() == PCB_VIA_T ? DRCE_DANGLING_VIA : DRCE_DANGLING_TRACK; |
|||
wxPoint pos; |
|||
|
|||
if( track->Type() == PCB_VIA_T && exceedV ) |
|||
continue; |
|||
else if( track->Type() == PCB_TRACE_T && exceedT ) |
|||
continue; |
|||
|
|||
if( connectivity->TestTrackEndpointDangling( track, &pos ) ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( code ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() ); |
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( track ); |
|||
ReportWithMarker( drcItem, pos ); |
|||
} |
|||
|
|||
if( exceedV && exceedT ) |
|||
break; |
|||
} |
|||
|
|||
ReportStage( ( "Testing starved zones" ), 0, 2 ); |
|||
|
|||
/* test starved zones */ |
|||
for( auto zone : board->Zones() ) |
|||
{ |
|||
if( !zone->IsOnCopperLayer() ) |
|||
continue; |
|||
|
|||
int netcode = zone->GetNetCode(); |
|||
// a netcode < 0 or > 0 and no pad in net is a error or strange
|
|||
// perhaps a "dead" net, which happens when all pads in this net were removed
|
|||
// Remark: a netcode < 0 should not happen (this is more a bug somewhere)
|
|||
int pads_in_net = ( netcode > 0 ) ? connectivity->GetPadCount( netcode ) : 1; |
|||
|
|||
if( ( netcode < 0 ) || pads_in_net == 0 ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONE_HAS_EMPTY_NET ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() ); |
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( zone ); |
|||
ReportWithMarker( drcItem, zone->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_ZONE_HAS_EMPTY_NET ) ) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
ReportStage( ( "Testing unconnected ratlines" ), 0, 2 ); |
|||
|
|||
connectivity->RecalculateRatsnest(); |
|||
std::vector<CN_EDGE> edges; |
|||
connectivity->GetUnconnectedEdges( edges ); |
|||
|
|||
for( const CN_EDGE& edge : edges ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNCONNECTED_ITEMS ); |
|||
|
|||
drcItem->SetItems( edge.GetSourceNode()->Parent(), edge.GetTargetNode()->Parent() ); |
|||
ReportWithMarker( drcItem, edge.GetSourceNode()->Pos() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_UNCONNECTED_ITEMS ) ) |
|||
break; |
|||
} |
|||
|
|||
reportRuleStatistics(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> |
|||
test::DRC_TEST_PROVIDER_CONNECTIVITY::GetMatchingConstraintIds() const |
|||
{ |
|||
return {}; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_CONNECTIVITY> dummy; |
|||
} |
|||
@ -0,0 +1,229 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <common.h>
|
|||
#include <class_board.h>
|
|||
#include <class_drawsegment.h>
|
|||
#include <class_pad.h>
|
|||
|
|||
#include <convert_basic_shapes_to_polygon.h>
|
|||
#include <geometry/polygon_test_point_inside.h>
|
|||
|
|||
#include <geometry/seg.h>
|
|||
#include <geometry/shape_poly_set.h>
|
|||
#include <geometry/shape_rect.h>
|
|||
#include <geometry/shape_segment.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider_clearance_base.h>
|
|||
|
|||
/*
|
|||
Couartyard clearance. Tests for malformed component courtyards and overlapping footprints. |
|||
Generated errors: |
|||
- DRCE_OVERLAPPING_FOOTPRINTS |
|||
- DRCE_MISSING_COURTYARD |
|||
- DRCE_MALFORMED_COURTYARD |
|||
|
|||
TODO: do an actual clearance check instead of polygon intersection. Treat closed outlines |
|||
as filled and allow open curves in the courtyard. |
|||
*/ |
|||
|
|||
namespace test { |
|||
|
|||
class DRC_TEST_PROVIDER_COURTYARD_CLEARANCE : public DRC_TEST_PROVIDER_CLEARANCE_BASE |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_COURTYARD_CLEARANCE () |
|||
{ |
|||
m_isRuleDriven = false; |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_COURTYARD_CLEARANCE () |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "courtyard_clearance"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests components' courtyard clearance"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
|
|||
private: |
|||
|
|||
void testFootprintCourtyardDefinitions(); |
|||
void testOverlappingComponentCourtyards(); |
|||
|
|||
}; |
|||
|
|||
}; |
|||
|
|||
|
|||
void test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testFootprintCourtyardDefinitions() |
|||
{ |
|||
ReportStage( _("Testing component courtyard definitions"), 0, 2 ); |
|||
|
|||
for( MODULE* footprint : m_board->Modules() ) |
|||
{ |
|||
if( footprint->BuildPolyCourtyard() ) |
|||
{ |
|||
if( footprint->GetPolyCourtyardFront().OutlineCount() == 0 |
|||
&& footprint->GetPolyCourtyardBack().OutlineCount() == 0 ) |
|||
{ |
|||
if( isErrorLimitExceeded( DRCE_MISSING_COURTYARD ) ) |
|||
continue; |
|||
|
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_COURTYARD ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText( )); |
|||
|
|||
drcItem->SetItems( footprint ); |
|||
ReportWithMarker( drcItem, footprint->GetPosition() ); |
|||
} |
|||
else |
|||
{ |
|||
footprint->GetPolyCourtyardFront().BuildBBoxCaches(); |
|||
footprint->GetPolyCourtyardBack().BuildBBoxCaches(); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if( !isErrorLimitExceeded( DRCE_MALFORMED_COURTYARD) ) |
|||
{ |
|||
wxString msg; |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MALFORMED_COURTYARD ); |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( footprint ); |
|||
ReportWithMarker( drcItem, footprint->GetPosition() ); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
void test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::testOverlappingComponentCourtyards() |
|||
{ |
|||
ReportStage( _("Testing component courtyard overlap"), 0, 2 ); |
|||
|
|||
for( auto it1 = m_board->Modules().begin(); it1 != m_board->Modules().end(); it1++ ) |
|||
{ |
|||
MODULE* footprint = *it1; |
|||
SHAPE_POLY_SET& footprintFront = footprint->GetPolyCourtyardFront(); |
|||
SHAPE_POLY_SET& footprintBack = footprint->GetPolyCourtyardBack(); |
|||
|
|||
if( footprintFront.OutlineCount() == 0 && footprintBack.OutlineCount() == 0 ) |
|||
continue; // No courtyards defined
|
|||
|
|||
for( auto it2 = it1 + 1; it2 != m_board->Modules().end(); it2++ ) |
|||
{ |
|||
MODULE* test = *it2; |
|||
SHAPE_POLY_SET& testFront = test->GetPolyCourtyardFront(); |
|||
SHAPE_POLY_SET& testBack = test->GetPolyCourtyardBack(); |
|||
SHAPE_POLY_SET intersection; |
|||
bool overlap = false; |
|||
wxPoint pos; |
|||
|
|||
if( footprintFront.OutlineCount() > 0 && testFront.OutlineCount() > 0 |
|||
&& footprintFront.BBoxFromCaches().Intersects( testFront.BBoxFromCaches() ) ) |
|||
{ |
|||
intersection.RemoveAllContours(); |
|||
intersection.Append( footprintFront ); |
|||
|
|||
// Build the common area between footprint and the test:
|
|||
intersection.BooleanIntersection( testFront, SHAPE_POLY_SET::PM_FAST ); |
|||
|
|||
// If the intersection exists then they overlap
|
|||
if( intersection.OutlineCount() > 0 ) |
|||
{ |
|||
overlap = true; |
|||
pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); |
|||
} |
|||
} |
|||
|
|||
if( footprintBack.OutlineCount() > 0 && testBack.OutlineCount() > 0 |
|||
&& footprintBack.BBoxFromCaches().Intersects( testBack.BBoxFromCaches() ) ) |
|||
{ |
|||
intersection.RemoveAllContours(); |
|||
intersection.Append( footprintBack ); |
|||
|
|||
intersection.BooleanIntersection( testBack, SHAPE_POLY_SET::PM_FAST ); |
|||
|
|||
if( intersection.OutlineCount() > 0 ) |
|||
{ |
|||
overlap = true; |
|||
pos = (wxPoint) intersection.CVertex( 0, 0, -1 ); |
|||
} |
|||
} |
|||
|
|||
if( overlap ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_OVERLAPPING_FOOTPRINTS ); |
|||
drcItem->SetItems( footprint, test ); |
|||
ReportWithMarker ( drcItem, pos ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_OVERLAPPING_FOOTPRINTS ) ) |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::Run() |
|||
{ |
|||
m_board = m_drcEngine->GetBoard(); |
|||
|
|||
// fixme: don't use polygon intersection but distance for clearance tests
|
|||
//m_largestClearance = 0;
|
|||
//ReportAux( "Worst courtyard clearance : %d nm", m_largestClearance );
|
|||
|
|||
testFootprintCourtyardDefinitions(); |
|||
testOverlappingComponentCourtyards(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE::GetMatchingConstraintIds() const |
|||
{ |
|||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_COURTYARD_CLEARANCE }; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_COURTYARD_CLEARANCE> dummy; |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <geometry/shape.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
/*
|
|||
"Disallow" test. Goes through all items, matching types/conditions drop errors. |
|||
Errors generated: |
|||
- DRCE_ALLOWED_ITEMS |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_DISALLOW : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_DISALLOW() |
|||
{ |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_DISALLOW() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "disallow"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests for disallowed items (e.g. keepouts)"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
|
|||
private: |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_DISALLOW::Run() |
|||
{ |
|||
if( !m_drcEngine->HasCorrectRulesForId( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW ) ) |
|||
{ |
|||
ReportAux( "No disallow constraints found. Skipping check." ); |
|||
return false; |
|||
} |
|||
|
|||
ReportStage( ("Testing for disallow constraints"), 0, 2 ); |
|||
|
|||
auto checkItem = [&] ( BOARD_ITEM *item ) -> bool |
|||
{ |
|||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( |
|||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW, item ); |
|||
|
|||
if( constraint.Allowed() ) |
|||
return true; |
|||
|
|||
if( ( constraint.GetAllowedLayers() & item->GetLayerSet() ).any() ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( |
|||
drcItem->GetErrorText() + _( " (%s)" ), constraint.GetParentRule()->GetName() ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( item ); |
|||
drcItem->SetViolatingRule( constraint.GetParentRule() ); |
|||
|
|||
ReportWithMarker( drcItem, item->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_ALLOWED_ITEMS ) ) |
|||
return false; |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
forEachGeometryItem( {}, LSET::AllLayersMask(), checkItem ); |
|||
|
|||
reportRuleStatistics(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> |
|||
test::DRC_TEST_PROVIDER_DISALLOW::GetMatchingConstraintIds() const |
|||
{ |
|||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_DISALLOW }; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_DISALLOW> dummy; |
|||
} |
|||
@ -0,0 +1,214 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
#include <kiway.h>
|
|||
#include <netlist_reader/pcb_netlist.h>
|
|||
|
|||
/*
|
|||
Layout-versus-schematic (LVS) test. |
|||
|
|||
Errors generated: |
|||
- DRCE_MISSING_FOOTPRINT |
|||
- DRCE_DUPLICATE_FOOTPRINT |
|||
- DRCE_EXTRA_FOOTPRINT |
|||
|
|||
TODO: |
|||
- cross-check PCB netlist against SCH netlist |
|||
- cross-check PCB fields against SCH fields |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_LVS : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_LVS() |
|||
{ |
|||
m_isRuleDriven = false; |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_LVS() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "LVS"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Performs layout-vs-schematics integity check"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
|
|||
private: |
|||
|
|||
bool fetchNetlistFromSchematic( NETLIST& aNetlist ); |
|||
void testFootprints( NETLIST& aNetlist ); |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
void test::DRC_TEST_PROVIDER_LVS::testFootprints( NETLIST& aNetlist ) |
|||
{ |
|||
wxString msg; |
|||
BOARD* board = m_drcEngine->GetBoard(); |
|||
|
|||
auto comp = []( const MODULE* x, const MODULE* y ) { |
|||
return x->GetReference().CmpNoCase( y->GetReference() ) < 0; |
|||
}; |
|||
|
|||
auto mods = std::set<MODULE*, decltype( comp )>( comp ); |
|||
|
|||
for( MODULE* mod : board->Modules() ) |
|||
{ |
|||
auto ins = mods.insert( mod ); |
|||
|
|||
if( !ins.second ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DUPLICATE_FOOTPRINT ); |
|||
drcItem->SetItems( mod, *ins.first ); |
|||
|
|||
ReportWithMarker( drcItem, mod->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_DUPLICATE_FOOTPRINT ) ) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
// Search for component footprints in the netlist but not on the board.
|
|||
for( unsigned ii = 0; ii < aNetlist.GetCount(); ii++ ) |
|||
{ |
|||
COMPONENT* component = aNetlist.GetComponent( ii ); |
|||
MODULE* module = board->FindModuleByReference( component->GetReference() ); |
|||
|
|||
if( module == nullptr ) |
|||
{ |
|||
msg.Printf( _( "Missing footprint %s (%s)" ), component->GetReference(), |
|||
component->GetValue() ); |
|||
|
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_MISSING_FOOTPRINT ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
Report( drcItem ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_MISSING_FOOTPRINT ) ) |
|||
break; |
|||
} |
|||
} |
|||
|
|||
|
|||
for( auto module : mods ) |
|||
{ |
|||
COMPONENT* component = aNetlist.GetComponentByReference( module->GetReference() ); |
|||
|
|||
if( component == NULL ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_EXTRA_FOOTPRINT ); |
|||
|
|||
drcItem->SetItems( module ); |
|||
ReportWithMarker( drcItem, module->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_EXTRA_FOOTPRINT ) ) |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_LVS::fetchNetlistFromSchematic( NETLIST& aNetlist ) |
|||
{ |
|||
// fixme: make it work without dependency on EDIT_FRAME/kiway
|
|||
#if 0
|
|||
std::string payload; |
|||
|
|||
Kiway().ExpressMail( FRAME_SCH, MAIL_SCH_GET_NETLIST, payload, nullptr ); |
|||
|
|||
try |
|||
{ |
|||
auto lineReader = new STRING_LINE_READER( payload, _( "Eeschema netlist" ) ); |
|||
KICAD_NETLIST_READER netlistReader( lineReader, &aNetlist ); |
|||
netlistReader.LoadNetlist(); |
|||
} |
|||
catch( const IO_ERROR& ) |
|||
{ |
|||
assert( false ); // should never happen
|
|||
return false; |
|||
} |
|||
|
|||
#endif
|
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool test::DRC_TEST_PROVIDER_LVS::Run() |
|||
{ |
|||
ReportStage( _( "Layout-vs-Schematic checks..." ), 0, 2 ); |
|||
|
|||
#if 0
|
|||
|
|||
if ( !Kiface().IsSingle() ) |
|||
{ |
|||
NETLIST netlist; // fixme: fetch from schematic without referring directly to the FRAME
|
|||
|
|||
if( ! fetchNetlistFromSchematic( netlist ) ) |
|||
{ |
|||
ReportAux( _( "Unable to fetch the schematic netlist. Skipping LVS checks. ") ); |
|||
return true; |
|||
} |
|||
|
|||
testFootprints( netlist ); |
|||
} |
|||
#endif
|
|||
|
|||
reportRuleStatistics(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_LVS::GetMatchingConstraintIds() const |
|||
{ |
|||
return {}; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_LVS> dummy; |
|||
} |
|||
@ -0,0 +1,216 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <class_module.h>
|
|||
#include <class_pcb_text.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
#include <ws_draw_item.h>
|
|||
#include <ws_proxy_view_item.h>
|
|||
|
|||
/*
|
|||
Miscellaneous tests: |
|||
|
|||
- DRCE_DISABLED_LAYER_ITEM, ///< item on a disabled layer
|
|||
- DRCE_INVALID_OUTLINE, ///< invalid board outline
|
|||
- DRCE_UNRESOLVED_VARIABLE, |
|||
|
|||
TODO: |
|||
- if grows too big, split into separate providers |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_MISC : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_MISC() |
|||
{ |
|||
m_isRuleDriven = false; |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_MISC() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "miscellanous"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Misc checks (board outline, missing textvars)"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
|
|||
private: |
|||
void testOutline(); |
|||
void testDisabledLayers(); |
|||
void testTextVars(); |
|||
|
|||
BOARD* m_board; |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
void test::DRC_TEST_PROVIDER_MISC::testOutline() |
|||
{ |
|||
wxPoint error_loc( m_board->GetBoardEdgesBoundingBox().GetPosition() ); |
|||
|
|||
SHAPE_POLY_SET boardOutlines; |
|||
|
|||
if( m_board->GetBoardPolygonOutlines( boardOutlines, nullptr, &error_loc ) ) |
|||
return; |
|||
|
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_INVALID_OUTLINE ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (not a closed shape)" ) ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( m_board ); |
|||
|
|||
ReportWithMarker( drcItem, error_loc ); |
|||
} |
|||
|
|||
|
|||
void test::DRC_TEST_PROVIDER_MISC::testDisabledLayers() |
|||
{ |
|||
LSET disabledLayers = m_board->GetEnabledLayers().flip(); |
|||
|
|||
|
|||
// Perform the test only for copper layers
|
|||
disabledLayers &= LSET::AllCuMask(); |
|||
|
|||
auto checkDisabledLayers = [&]( BOARD_ITEM* item ) -> bool { |
|||
if( ( disabledLayers & item->GetLayerSet() ).any() ) |
|||
{ |
|||
wxString msg; |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_DISABLED_LAYER_ITEM ); |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (layer %s)" ), item->GetLayerName() ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( item ); |
|||
|
|||
ReportWithMarker( drcItem, item->GetPosition() ); |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
// fixme: what about graphical items?
|
|||
forEachGeometryItem( { PCB_TRACE_T, PCB_ARC_T, PCB_VIA_T, PCB_ZONE_AREA_T, PCB_PAD_T }, |
|||
LSET::AllLayersMask(), checkDisabledLayers ); |
|||
} |
|||
|
|||
void test::DRC_TEST_PROVIDER_MISC::testTextVars() |
|||
{ |
|||
auto checkUnresolvedTextVar = [&]( EDA_ITEM* item ) -> bool { |
|||
EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( item ); |
|||
|
|||
assert( text ); |
|||
|
|||
|
|||
if( text->GetShownText().Matches( wxT( "*${*}*" ) ) ) |
|||
{ |
|||
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) |
|||
return false; |
|||
|
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); |
|||
drcItem->SetItems( item ); |
|||
|
|||
ReportWithMarker( drcItem, item->GetPosition() ); |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
forEachGeometryItem( |
|||
{ PCB_MODULE_TEXT_T, PCB_TEXT_T }, LSET::AllLayersMask(), checkUnresolvedTextVar ); |
|||
|
|||
WS_DRAW_ITEM_LIST wsItems; |
|||
|
|||
auto worksheet = m_drcEngine->GetWorksheet(); |
|||
|
|||
if( !worksheet ) |
|||
return; |
|||
|
|||
wsItems.SetMilsToIUfactor( IU_PER_MILS ); |
|||
wsItems.BuildWorkSheetGraphicList( worksheet->GetPageInfo(), worksheet->GetTitleBlock() ); |
|||
|
|||
for( WS_DRAW_ITEM_BASE* item = wsItems.GetFirst(); item; item = wsItems.GetNext() ) |
|||
{ |
|||
if( WS_DRAW_ITEM_TEXT* text = dynamic_cast<WS_DRAW_ITEM_TEXT*>( item ) ) |
|||
{ |
|||
if( isErrorLimitExceeded( DRCE_UNRESOLVED_VARIABLE ) ) |
|||
return; |
|||
|
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_UNRESOLVED_VARIABLE ); |
|||
drcItem->SetItems( text ); |
|||
|
|||
ReportWithMarker( drcItem, text->GetPosition() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_MISC::Run() |
|||
{ |
|||
m_board = m_drcEngine->GetBoard(); |
|||
|
|||
ReportStage( _( "Test board outline" ), 0, 3 ); |
|||
testOutline(); |
|||
|
|||
ReportStage( _( "Test disabled layers" ), 1, 3 ); |
|||
testDisabledLayers(); |
|||
|
|||
ReportStage( _( "Test text variables" ), 2, 3 ); |
|||
testTextVars(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_MISC::GetMatchingConstraintIds() const |
|||
{ |
|||
return {}; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_MISC> dummy; |
|||
} |
|||
@ -0,0 +1,168 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <common.h>
|
|||
#include <class_board.h>
|
|||
#include <class_drawsegment.h>
|
|||
#include <class_pad.h>
|
|||
|
|||
#include <convert_basic_shapes_to_polygon.h>
|
|||
#include <geometry/polygon_test_point_inside.h>
|
|||
|
|||
#include <geometry/seg.h>
|
|||
#include <geometry/shape_poly_set.h>
|
|||
#include <geometry/shape_rect.h>
|
|||
#include <geometry/shape_segment.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider_clearance_base.h>
|
|||
|
|||
/*
|
|||
Silk to pads clearance test. Check all pads against silkscreen (mask opening in the pad vs silkscreen) |
|||
Errors generated: |
|||
- DRCE_SILK_ON_PADS |
|||
|
|||
TODO: |
|||
- tester only looks for edge crossings. it doesn't check if items are inside/outside the board area. |
|||
*/ |
|||
|
|||
namespace test { |
|||
|
|||
class DRC_TEST_PROVIDER_SILK_TO_PAD : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_SILK_TO_PAD () |
|||
{ |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_SILK_TO_PAD() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "silk_to_pad"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests for silkscreen covering components pads"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
|
|||
private: |
|||
}; |
|||
|
|||
}; |
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_SILK_TO_PAD::Run() |
|||
{ |
|||
m_board = m_drcEngine->GetBoard(); |
|||
|
|||
DRC_CONSTRAINT worstClearanceConstraint; |
|||
m_largestClearance = 0; |
|||
|
|||
if( m_drcEngine->QueryWorstConstraint( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_SILK_TO_PAD, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) ) |
|||
{ |
|||
m_largestClearance = worstClearanceConstraint.m_Value.Min(); |
|||
} |
|||
|
|||
ReportAux( "Worst clearance : %d nm", m_largestClearance ); |
|||
ReportStage( ("Testing pads vs silkscreen clearance"), 0, 2 ); |
|||
|
|||
|
|||
std::vector<DRAWSEGMENT*> boardOutline; |
|||
std::vector<BOARD_ITEM*> boardItems; |
|||
|
|||
auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int |
|||
{ |
|||
boardOutline.push_back( dyn_cast<DRAWSEGMENT*>( item ) ); |
|||
}; |
|||
|
|||
auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int |
|||
{ |
|||
boardItems.push_back( item ); |
|||
}; |
|||
|
|||
|
|||
|
|||
forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems ); |
|||
forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems ); |
|||
|
|||
|
|||
drc_dbg(2,"outline: %d items, board: %d items\n", boardOutline.size(), boardItems.size() ); |
|||
|
|||
for( auto outlineItem : boardOutline ) |
|||
{ |
|||
//printf("RefT %d\n", outlineItem->Type() );
|
|||
auto refShape = outlineItem->GetEffectiveShape(); |
|||
|
|||
for( auto boardItem : boardItems ) |
|||
{ |
|||
// printf("BoardT %d\n", boardItem->Type() );
|
|||
|
|||
auto shape = boardItem->GetEffectiveShape(); |
|||
|
|||
test::DRC_RULE* rule = m_drcEngine->EvalRulesForItems( test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE, outlineItem, boardItem ); |
|||
int minClearance = rule->GetConstraint().GetValue().Min(); |
|||
int actual; |
|||
|
|||
if( refShape->Collide( shape.get(), minClearance, &actual ) ) |
|||
{ |
|||
DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_COPPER_EDGE_CLEARANCE ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ), |
|||
rule->GetName(), |
|||
MessageTextFromValue( userUnits(), minClearance, true ), |
|||
MessageTextFromValue( userUnits(), actual, true ) ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( outlineItem, boardItem ); |
|||
drcItem->SetViolatingRule( rule ); |
|||
|
|||
ReportWithMarker( drcItem, refShape->Centre() ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::GetMatchingConstraintIds() const |
|||
{ |
|||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_EDGE_CLEARANCE }; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_EDGE_CLEARANCE> dummy; |
|||
} |
|||
@ -0,0 +1,154 @@ |
|||
/*
|
|||
* This program source code file is part of KiCad, a free EDA CAD application. |
|||
* |
|||
* Copyright (C) 2004-2020 KiCad Developers. |
|||
* |
|||
* This program is free software; you can redistribute it and/or |
|||
* modify it under the terms of the GNU General Public License |
|||
* as published by the Free Software Foundation; either version 2 |
|||
* of the License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, you may find one here: |
|||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|||
* or you may search the http://www.gnu.org website for the version 2 license,
|
|||
* or you may write to the Free Software Foundation, Inc., |
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA |
|||
*/ |
|||
|
|||
#include <class_board.h>
|
|||
#include <class_track.h>
|
|||
#include <common.h>
|
|||
|
|||
#include <drc_proto/drc_engine.h>
|
|||
#include <drc_proto/drc_item.h>
|
|||
#include <drc_proto/drc_rule.h>
|
|||
#include <drc_proto/drc_test_provider.h>
|
|||
|
|||
|
|||
/*
|
|||
Via diameter test. |
|||
|
|||
Errors generated: |
|||
- DRCE_TOO_SMALL_VIA |
|||
- DRCE_TOO_SMALL_MICROVIA |
|||
*/ |
|||
|
|||
namespace test |
|||
{ |
|||
|
|||
class DRC_TEST_PROVIDER_VIA_DIAMETER : public DRC_TEST_PROVIDER |
|||
{ |
|||
public: |
|||
DRC_TEST_PROVIDER_VIA_DIAMETER() |
|||
{ |
|||
} |
|||
|
|||
virtual ~DRC_TEST_PROVIDER_VIA_DIAMETER() |
|||
{ |
|||
} |
|||
|
|||
virtual bool Run() override; |
|||
|
|||
virtual const wxString GetName() const override |
|||
{ |
|||
return "diameter"; |
|||
}; |
|||
|
|||
virtual const wxString GetDescription() const override |
|||
{ |
|||
return "Tests via diameters"; |
|||
} |
|||
|
|||
virtual std::set<test::DRC_CONSTRAINT_TYPE_T> GetMatchingConstraintIds() const override; |
|||
}; |
|||
|
|||
}; // namespace test
|
|||
|
|||
|
|||
bool test::DRC_TEST_PROVIDER_VIA_DIAMETER::Run() |
|||
{ |
|||
if( !m_drcEngine->HasCorrectRulesForId( |
|||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER ) ) |
|||
{ |
|||
ReportAux( "No diameter constraints found. Skipping check." ); |
|||
return false; |
|||
} |
|||
|
|||
ReportStage( ( "Testing via diameters" ), 0, 2 ); |
|||
|
|||
auto checkViaDiameter = [&]( BOARD_ITEM* item ) -> bool { |
|||
auto via = dyn_cast<VIA*>( item ); |
|||
|
|||
// fixme: move to pad stack check?
|
|||
if( !via ) |
|||
return true; |
|||
|
|||
test::DRC_CONSTRAINT constraint = m_drcEngine->EvalRulesForItems( |
|||
test::DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER, item ); |
|||
|
|||
bool fail_min = false, fail_max = false; |
|||
int constraintDiameter; |
|||
int diameter = via->GetWidth(); |
|||
|
|||
if( constraint.Value().HasMin() && diameter < constraint.Value().Min() ) |
|||
{ |
|||
fail_min = true; |
|||
constraintDiameter = constraint.Value().Min(); |
|||
} |
|||
|
|||
if( constraint.Value().HasMax() && diameter > constraint.Value().Max() ) |
|||
{ |
|||
fail_max = true; |
|||
constraintDiameter = constraint.Value().Max(); |
|||
} |
|||
|
|||
if( fail_min || fail_max ) |
|||
{ |
|||
std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_VIA_DIAMETER ); |
|||
wxString msg; |
|||
|
|||
msg.Printf( drcItem->GetErrorText() + _( " (%s; diameter %s, constraint %s %s)" ), |
|||
constraint.GetParentRule()->GetName(), |
|||
MessageTextFromValue( userUnits(), diameter, true ), |
|||
fail_min ? _( "minimum" ) : _( "maximum" ), |
|||
MessageTextFromValue( userUnits(), constraintDiameter, true ) ); |
|||
|
|||
drcItem->SetErrorMessage( msg ); |
|||
drcItem->SetItems( item ); |
|||
drcItem->SetViolatingRule( constraint.GetParentRule() ); |
|||
|
|||
ReportWithMarker( drcItem, via->GetPosition() ); |
|||
|
|||
if( isErrorLimitExceeded( DRCE_VIA_DIAMETER ) ) |
|||
return false; |
|||
|
|||
} |
|||
|
|||
return true; |
|||
}; |
|||
|
|||
forEachGeometryItem( { PCB_VIA_T }, LSET::AllCuMask(), checkViaDiameter ); |
|||
|
|||
reportRuleStatistics(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
|
|||
std::set<test::DRC_CONSTRAINT_TYPE_T> |
|||
test::DRC_TEST_PROVIDER_VIA_DIAMETER::GetMatchingConstraintIds() const |
|||
{ |
|||
return { DRC_CONSTRAINT_TYPE_T::DRC_CONSTRAINT_TYPE_VIA_DIAMETER }; |
|||
} |
|||
|
|||
|
|||
namespace detail |
|||
{ |
|||
static test::DRC_REGISTER_TEST_PROVIDER<test::DRC_TEST_PROVIDER_VIA_DIAMETER> dummy; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue