KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_drc_copper_graphics.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
22#include <board.h>
24#include <drc/drc_engine.h>
25#include <drc/drc_rtree.h>
26#include <footprint.h>
27#include <netclass.h>
28#include <pad.h>
29#include <pcb_marker.h>
30#include <pcb_shape.h>
31#include <pcb_track.h>
33#include <drc/drc_item.h>
35
36
45
46
47static void runLineEndingMatrixDrcTest( SETTINGS_MANAGER& aSettingsManager, std::unique_ptr<BOARD>& aBoard,
48 const wxString& aBoardName, int aExpectedViolationCount )
49{
50 KI_TEST::LoadBoard( aSettingsManager, aBoardName, aBoard );
51
52 BOARD_DESIGN_SETTINGS& bds = aBoard->GetDesignSettings();
53
54 for( int code = 0; code < DRCE_LAST; ++code )
56
59
60 std::vector<DRC_ITEM> violations;
61
63 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I&, int,
64 const std::function<void( PCB_MARKER* )>& )
65 {
66 if( aItem->GetErrorCode() == DRCE_CLEARANCE || aItem->GetErrorCode() == DRCE_SHORTING_ITEMS )
67 {
68 violations.push_back( *aItem );
69 }
70 } );
71
72 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
74
75 if( (int) violations.size() == aExpectedViolationCount )
76 {
77 BOOST_CHECK_EQUAL( violations.size(), (size_t) aExpectedViolationCount );
78 return;
79 }
80
82
83 wxString report;
84 BOARD_RC_ITEM_RESOLVER resolver( *aBoard );
85
86 for( const DRC_ITEM& item : violations )
87 report += item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, resolver );
88
89 BOOST_ERROR( wxString::Format( "DRC line ending matrix: %s\n"
90 "%d violations found (expected %d)\n"
91 "%s",
92 aBoardName, (int) violations.size(), aExpectedViolationCount, report ) );
93}
94
95
97{
98 wxString brd_name( wxT( "test_copper_graphics" ) );
99 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
100
101 // Do NOT refill zones; this will prevent some of the items from being tested.
102 // KI_TEST::FillZones( m_board.get() );
103
104 std::vector<DRC_ITEM> violations;
105 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
106
107 // Disable some DRC tests not useful in this testcase (and time consuming)
116
118 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
119 const std::function<void( PCB_MARKER* )>& aPathGenerator )
120 {
121 PCB_MARKER temp( aItem, aPos );
122
123 if( bds.m_DrcExclusions.find( DRC_EXCLUSION::FromMarker( temp ) ) == bds.m_DrcExclusions.end() )
124 violations.push_back( *aItem );
125 } );
126
127 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
128
129 const int expected_err_cnt = 4; // "What" copper text shorting zone
130 // Copper knockout text shorting two zones twice (but not
131 // three times as the two vertical zones are the same net)
132 // Net-tie rectangle shorting zone
133
134 if( violations.size() == expected_err_cnt )
135 {
136 BOOST_CHECK_EQUAL( 1, 1 ); // quiet "did not check any assertions" warning
137 BOOST_TEST_MESSAGE( "DRC copper graphics test passed" );
138 }
139 else
140 {
141 BOOST_CHECK_EQUAL( violations.size(), expected_err_cnt );
142
143 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::INCH );
144
145 wxString report;
146 BOARD_RC_ITEM_RESOLVER resolver( *m_board );
147
148 for( const DRC_ITEM& item : violations )
149 report += item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, resolver );
150
151 BOOST_ERROR( wxString::Format( "DRC copper graphics: %s\n"
152 "%d violations found (expected %d)\n"
153 "%s",
154 brd_name,
155 (int) violations.size(),
156 expected_err_cnt,
157 report ) );
158 }
159}
160
161
163{
164 struct MATRIX_CASE
165 {
166 wxString boardName;
167 int expectedViolations;
168 };
169
170 const MATRIX_CASE cases[] = {
171 { wxT( "line_ending_drc/line_ending_drc_fail" ), 123 },
172 { wxT( "line_ending_drc/line_ending_drc_pass" ), 0 },
173 };
174
175 for( const MATRIX_CASE& testCase : cases )
176 {
177 runLineEndingMatrixDrcTest( m_settingsManager, m_board, testCase.boardName, testCase.expectedViolations );
178 }
179}
180
181
182BOOST_FIXTURE_TEST_CASE( DRCCopperGraphicLineEndingAgainstTrack, DRC_COPPER_GRAPHICS_TEST_FIXTURE )
183{
184 m_board = std::make_unique<BOARD>();
185 m_board->SetCopperLayerCount( 2 );
186
187 NETINFO_ITEM* netA = new NETINFO_ITEM( m_board.get(), wxS( "A" ), 1 );
188 NETINFO_ITEM* netB = new NETINFO_ITEM( m_board.get(), wxS( "B" ), 2 );
189 m_board->Add( netA );
190 m_board->Add( netB );
191
192 auto addPad = [&]( const VECTOR2I& aPos, NETINFO_ITEM* aNet )
193 {
194 FOOTPRINT* fp = new FOOTPRINT( m_board.get() );
195 fp->SetPosition( aPos );
196 m_board->Add( fp );
197
198 PAD* pad = new PAD( fp );
199 pad->SetPadstackMode( PADSTACK::MODE::NORMAL );
200 pad->SetAttribute( PAD_ATTRIB::SMD );
202 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( pcbIUScale.mmToIU( 0.4 ), pcbIUScale.mmToIU( 0.4 ) ) );
203 pad->SetLayerSet( LSET( { F_Cu } ) );
204 pad->SetPosition( aPos );
205 pad->SetNet( aNet );
206 fp->Add( pad );
207
208 return pad;
209 };
210
211 PCB_SHAPE* graphic = new PCB_SHAPE( m_board.get(), SHAPE_T::SEGMENT );
212 graphic->SetLayer( F_Cu );
213 graphic->SetStart( VECTOR2I( 0, 0 ) );
214 graphic->SetEnd( VECTOR2I( 0, pcbIUScale.mmToIU( 4.0 ) ) );
215 graphic->SetWidth( pcbIUScale.mmToIU( 0.1 ) );
217 graphic->SetStartEndingLength( pcbIUScale.mmToIU( 1.0 ) );
218 graphic->SetStartEndingWidth( pcbIUScale.mmToIU( 1.0 ) );
219 graphic->SetNet( netA );
220 m_board->Add( graphic );
221 PAD* graphicPad = addPad( graphic->GetEnd(), netA );
222
223 PCB_TRACK* track = new PCB_TRACK( m_board.get() );
224 track->SetLayer( F_Cu );
225 track->SetStart( VECTOR2I( -pcbIUScale.mmToIU( 4.0 ), 0 ) );
226 track->SetEnd( VECTOR2I( pcbIUScale.mmToIU( 0.4 ), 0 ) );
227 track->SetWidth( pcbIUScale.mmToIU( 0.05 ) );
228 track->SetNet( netB );
229 m_board->Add( track );
230 PAD* trackPad = addPad( track->GetStart(), netB );
231
232 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
233 bds.m_MinClearance = pcbIUScale.mmToIU( 0.5 );
235
236 if( !bds.m_DRCEngine )
237 bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( m_board.get(), &bds );
238
239 bds.m_DRCEngine->InitEngine( wxFileName() );
240
241 for( int code = 0; code < DRCE_LAST; ++code )
243
246
247 BOOST_REQUIRE_EQUAL( m_board->Drawings().size(), 1 );
248 BOOST_REQUIRE_EQUAL( m_board->Tracks().size(), 1 );
249 BOOST_REQUIRE_EQUAL( graphicPad->GetNetCode(), netA->GetNetCode() );
250 BOOST_REQUIRE_EQUAL( trackPad->GetNetCode(), netB->GetNetCode() );
251 BOOST_REQUIRE_NE( graphic->GetNetCode(), track->GetNetCode() );
252
253 DRC_CONSTRAINT directConstraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, graphic, track, F_Cu );
254 BOOST_REQUIRE( directConstraint.GetSeverity() != RPT_SEVERITY_IGNORE );
255 BOOST_REQUIRE_GT( directConstraint.GetValue().Min(), 0 );
256
257 DRC_CONSTRAINT reverseConstraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, track, graphic, F_Cu );
258 BOOST_REQUIRE( reverseConstraint.GetSeverity() != RPT_SEVERITY_IGNORE );
259 BOOST_REQUIRE_GT( reverseConstraint.GetValue().Min(), 0 );
260
261 std::shared_ptr<SHAPE> trackShape = track->GetEffectiveShape( F_Cu );
262 std::shared_ptr<SHAPE> graphicShape = graphic->GetEffectiveShape( F_Cu );
263 int actual = 0;
264 VECTOR2I pos;
265
266 BOOST_REQUIRE( trackShape );
267 BOOST_REQUIRE( graphicShape );
268 BOOST_REQUIRE( trackShape->Collide( graphicShape.get(), directConstraint.GetValue().Min(), &actual, &pos ) );
269
270 int violationCount = 0;
271 std::vector<int> violationCodes;
272
274 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& /*aPos*/, int /*aLayer*/,
275 const std::function<void( PCB_MARKER* )>& /*aPathGenerator*/ )
276 {
277 violationCodes.push_back( aItem->GetErrorCode() );
278
279 if( aItem->GetErrorCode() == DRCE_CLEARANCE || aItem->GetErrorCode() == DRCE_SHORTING_ITEMS )
280 {
281 ++violationCount;
282 }
283 } );
284
285 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
287
288 BOOST_REQUIRE( m_board->m_CopperItemRTreeCache );
289 BOOST_CHECK_GE( m_board->m_CopperItemRTreeCache->QueryColliding( track, F_Cu, F_Cu,
290 [&]( BOARD_ITEM* other ) -> bool
291 {
292 return other == graphic;
293 } ),
294 1 );
295 BOOST_CHECK_GE( m_board->m_CopperItemRTreeCache->QueryColliding(
296 track, F_Cu, F_Cu,
297 [&]( BOARD_ITEM* other ) -> bool
298 {
299 return other == graphic;
300 },
301 nullptr, m_board->m_DRCMaxClearance ),
302 1 );
303
304 BOOST_CHECK_NE( graphic->GetNetCode(), track->GetNetCode() );
305
306 if( violationCount < 1 )
307 {
308 wxString codes;
309
310 for( int code : violationCodes )
311 codes += wxString::Format( wxT( " %d" ), code );
312
313 BOOST_TEST_MESSAGE( wxString::Format( wxT( "Reported violation codes:%s" ), codes ) );
314 }
315
316 BOOST_CHECK_GE( violationCount, 1 );
317}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
std::map< int, SEVERITY > m_DRCSeverities
std::shared_ptr< DRC_ENGINE > m_DRCEngine
std::set< DRC_EXCLUSION, DRC_EXCLUSION_COMPARE > m_DrcExclusions
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
Implements the RC_ITEM_RESOLVER interface to resolve PCB items by their KIID.
Definition drc_item.h:349
SEVERITY GetSeverity() const
Definition drc_rule.h:181
const MINOPTMAX< int > & GetValue() const
Definition drc_rule.h:129
void RunTests(EDA_UNITS aUnits, bool aReportAllTrackErrors, bool aTestFootprints, BOARD_COMMIT *aCommit=nullptr)
Run the DRC tests.
void SetViolationHandler(DRC_VIOLATION_HANDLER aHandler)
Set an optional DRC violation handler (receives DRC_ITEMs and positions).
Definition drc_engine.h:164
DRC_CONSTRAINT EvalRules(DRC_CONSTRAINT_T aConstraintType, const BOARD_ITEM *a, const BOARD_ITEM *b, PCB_LAYER_ID aLayer, REPORTER *aReporter=nullptr)
void ClearViolationHandler()
Definition drc_engine.h:169
void InitEngine(const wxFileName &aRulePath)
Initialize the DRC engine.
static DRC_EXCLUSION FromMarker(const PCB_MARKER &aMarker)
void SetStartEndingStyle(LINE_ENDING_STYLE aStyle)
Definition eda_shape.h:192
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:333
void SetStartEndingLength(int aLength)
Definition eda_shape.h:198
void SetStartEndingWidth(int aWidth)
Definition eda_shape.h:200
void SetPosition(const VECTOR2I &aPos) override
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Adds an item to the container.
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
T Min() const
Definition minoptmax.h:29
void SetClearance(int aClearance)
Definition netclass.h:144
Handle the data for a net.
Definition netinfo.h:50
int GetNetCode() const
Definition netinfo.h:104
std::shared_ptr< NETCLASS > GetDefaultNetclass() const
Gets the default netclass for the project.
@ NORMAL
Shape is the same on all layers.
Definition padstack.h:170
static constexpr PCB_LAYER_ID ALL_LAYERS
! The layer identifier to use for the single defintion on normal padstacks
Definition padstack.h:179
Definition pad.h:61
void SetWidth(int aWidth) override
void SetEnd(const VECTOR2I &aEnd) override
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
void SetStart(const VECTOR2I &aStart) override
void SetEnd(const VECTOR2I &aEnd)
Definition pcb_track.h:94
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:97
const VECTOR2I & GetStart() const
Definition pcb_track.h:98
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
virtual void SetWidth(int aWidth)
Definition pcb_track.h:91
@ CLEARANCE_CONSTRAINT
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:111
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:127
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:96
@ DRCE_STARVED_THERMAL
Definition drc_item.h:58
@ DRCE_CLEARANCE
Definition drc_item.h:52
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:57
@ DRCE_COPPER_SLIVER
Definition drc_item.h:107
@ DRCE_SHORTING_ITEMS
Definition drc_item.h:49
@ DRCE_LAST
Definition drc_item.h:144
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:97
@ DRCE_UNMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:128
@ SEGMENT
Definition eda_shape.h:56
@ F_Cu
Definition layer_ids.h:60
void LoadBoard(SETTINGS_MANAGER &aSettingsManager, const wxString &aRelPath, std::unique_ptr< BOARD > &aBoard)
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:98
@ RPT_SEVERITY_ERROR
@ RPT_SEVERITY_IGNORE
BOOST_FIXTURE_TEST_CASE(DRCCopperGraphicsTest, DRC_COPPER_GRAPHICS_TEST_FIXTURE)
static void runLineEndingMatrixDrcTest(SETTINGS_MANAGER &aSettingsManager, std::unique_ptr< BOARD > &aBoard, const wxString &aBoardName, int aExpectedViolationCount)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")
int actual
BOOST_CHECK_EQUAL(result, "25.4")
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708