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 std::map<KIID, EDA_ITEM*> itemMap;
85 aBoard->FillItemMap( itemMap );
86
87 for( const DRC_ITEM& item : violations )
88 report += item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, itemMap );
89
90 BOOST_ERROR( wxString::Format( "DRC line ending matrix: %s\n"
91 "%d violations found (expected %d)\n"
92 "%s",
93 aBoardName, (int) violations.size(), aExpectedViolationCount, report ) );
94}
95
96
98{
99 wxString brd_name( wxT( "test_copper_graphics" ) );
100 KI_TEST::LoadBoard( m_settingsManager, brd_name, m_board );
101
102 // Do NOT refill zones; this will prevent some of the items from being tested.
103 // KI_TEST::FillZones( m_board.get() );
104
105 std::vector<DRC_ITEM> violations;
106 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
107
108 // Disable some DRC tests not useful in this testcase (and time consuming)
117
119 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& aPos, int aLayer,
120 const std::function<void( PCB_MARKER* )>& aPathGenerator )
121 {
122 PCB_MARKER temp( aItem, aPos );
123
124 if( bds.m_DrcExclusions.find( DRC_EXCLUSION::FromMarker( temp ) ) == bds.m_DrcExclusions.end() )
125 violations.push_back( *aItem );
126 } );
127
128 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
129
130 const int expected_err_cnt = 4; // "What" copper text shorting zone
131 // Copper knockout text shorting two zones twice (but not
132 // three times as the two vertical zones are the same net)
133 // Net-tie rectangle shorting zone
134
135 if( violations.size() == expected_err_cnt )
136 {
137 BOOST_CHECK_EQUAL( 1, 1 ); // quiet "did not check any assertions" warning
138 BOOST_TEST_MESSAGE( "DRC copper graphics test passed" );
139 }
140 else
141 {
142 BOOST_CHECK_EQUAL( violations.size(), expected_err_cnt );
143
144 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::INCH );
145
146 wxString report;
147 std::map<KIID, EDA_ITEM*> itemMap;
148 m_board->FillItemMap( itemMap );
149
150 for( const DRC_ITEM& item : violations )
151 report += item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR, itemMap );
152
153 BOOST_ERROR( wxString::Format( "DRC copper graphics: %s\n"
154 "%d violations found (expected %d)\n"
155 "%s",
156 brd_name,
157 (int) violations.size(),
158 expected_err_cnt,
159 report ) );
160 }
161}
162
163
165{
166 struct MATRIX_CASE
167 {
168 wxString boardName;
169 int expectedViolations;
170 };
171
172 const MATRIX_CASE cases[] = {
173 { wxT( "line_ending_drc/line_ending_drc_fail" ), 123 },
174 { wxT( "line_ending_drc/line_ending_drc_pass" ), 0 },
175 };
176
177 for( const MATRIX_CASE& testCase : cases )
178 {
179 runLineEndingMatrixDrcTest( m_settingsManager, m_board, testCase.boardName, testCase.expectedViolations );
180 }
181}
182
183
184BOOST_FIXTURE_TEST_CASE( DRCCopperGraphicLineEndingAgainstTrack, DRC_COPPER_GRAPHICS_TEST_FIXTURE )
185{
186 m_board = std::make_unique<BOARD>();
187 m_board->SetCopperLayerCount( 2 );
188
189 NETINFO_ITEM* netA = new NETINFO_ITEM( m_board.get(), wxS( "A" ), 1 );
190 NETINFO_ITEM* netB = new NETINFO_ITEM( m_board.get(), wxS( "B" ), 2 );
191 m_board->Add( netA );
192 m_board->Add( netB );
193
194 auto addPad = [&]( const VECTOR2I& aPos, NETINFO_ITEM* aNet )
195 {
196 FOOTPRINT* fp = new FOOTPRINT( m_board.get() );
197 fp->SetPosition( aPos );
198 m_board->Add( fp );
199
200 PAD* pad = new PAD( fp );
201 pad->SetPadstackMode( PADSTACK::MODE::NORMAL );
202 pad->SetAttribute( PAD_ATTRIB::SMD );
204 pad->SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( pcbIUScale.mmToIU( 0.4 ), pcbIUScale.mmToIU( 0.4 ) ) );
205 pad->SetLayerSet( LSET( { F_Cu } ) );
206 pad->SetPosition( aPos );
207 pad->SetNet( aNet );
208 fp->Add( pad );
209
210 return pad;
211 };
212
213 PCB_SHAPE* graphic = new PCB_SHAPE( m_board.get(), SHAPE_T::SEGMENT );
214 graphic->SetLayer( F_Cu );
215 graphic->SetStart( VECTOR2I( 0, 0 ) );
216 graphic->SetEnd( VECTOR2I( 0, pcbIUScale.mmToIU( 4.0 ) ) );
217 graphic->SetWidth( pcbIUScale.mmToIU( 0.1 ) );
219 graphic->SetStartEndingLength( pcbIUScale.mmToIU( 1.0 ) );
220 graphic->SetStartEndingWidth( pcbIUScale.mmToIU( 1.0 ) );
221 graphic->SetNet( netA );
222 m_board->Add( graphic );
223 PAD* graphicPad = addPad( graphic->GetEnd(), netA );
224
225 PCB_TRACK* track = new PCB_TRACK( m_board.get() );
226 track->SetLayer( F_Cu );
227 track->SetStart( VECTOR2I( -pcbIUScale.mmToIU( 4.0 ), 0 ) );
228 track->SetEnd( VECTOR2I( pcbIUScale.mmToIU( 0.4 ), 0 ) );
229 track->SetWidth( pcbIUScale.mmToIU( 0.05 ) );
230 track->SetNet( netB );
231 m_board->Add( track );
232 PAD* trackPad = addPad( track->GetStart(), netB );
233
234 BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
235 bds.m_MinClearance = pcbIUScale.mmToIU( 0.5 );
237
238 if( !bds.m_DRCEngine )
239 bds.m_DRCEngine = std::make_shared<DRC_ENGINE>( m_board.get(), &bds );
240
241 bds.m_DRCEngine->InitEngine( wxFileName() );
242
243 for( int code = 0; code < DRCE_LAST; ++code )
245
248
249 BOOST_REQUIRE_EQUAL( m_board->Drawings().size(), 1 );
250 BOOST_REQUIRE_EQUAL( m_board->Tracks().size(), 1 );
251 BOOST_REQUIRE_EQUAL( graphicPad->GetNetCode(), netA->GetNetCode() );
252 BOOST_REQUIRE_EQUAL( trackPad->GetNetCode(), netB->GetNetCode() );
253 BOOST_REQUIRE_NE( graphic->GetNetCode(), track->GetNetCode() );
254
255 DRC_CONSTRAINT directConstraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, graphic, track, F_Cu );
256 BOOST_REQUIRE( directConstraint.GetSeverity() != RPT_SEVERITY_IGNORE );
257 BOOST_REQUIRE_GT( directConstraint.GetValue().Min(), 0 );
258
259 DRC_CONSTRAINT reverseConstraint = bds.m_DRCEngine->EvalRules( CLEARANCE_CONSTRAINT, track, graphic, F_Cu );
260 BOOST_REQUIRE( reverseConstraint.GetSeverity() != RPT_SEVERITY_IGNORE );
261 BOOST_REQUIRE_GT( reverseConstraint.GetValue().Min(), 0 );
262
263 std::shared_ptr<SHAPE> trackShape = track->GetEffectiveShape( F_Cu );
264 std::shared_ptr<SHAPE> graphicShape = graphic->GetEffectiveShape( F_Cu );
265 int actual = 0;
266 VECTOR2I pos;
267
268 BOOST_REQUIRE( trackShape );
269 BOOST_REQUIRE( graphicShape );
270 BOOST_REQUIRE( trackShape->Collide( graphicShape.get(), directConstraint.GetValue().Min(), &actual, &pos ) );
271
272 int violationCount = 0;
273 std::vector<int> violationCodes;
274
276 [&]( const std::shared_ptr<DRC_ITEM>& aItem, const VECTOR2I& /*aPos*/, int /*aLayer*/,
277 const std::function<void( PCB_MARKER* )>& /*aPathGenerator*/ )
278 {
279 violationCodes.push_back( aItem->GetErrorCode() );
280
281 if( aItem->GetErrorCode() == DRCE_CLEARANCE || aItem->GetErrorCode() == DRCE_SHORTING_ITEMS )
282 {
283 ++violationCount;
284 }
285 } );
286
287 bds.m_DRCEngine->RunTests( EDA_UNITS::MM, true, false );
289
290 BOOST_REQUIRE( m_board->m_CopperItemRTreeCache );
291 BOOST_CHECK_GE( m_board->m_CopperItemRTreeCache->QueryColliding( track, F_Cu, F_Cu,
292 [&]( BOARD_ITEM* other ) -> bool
293 {
294 return other == graphic;
295 } ),
296 1 );
297 BOOST_CHECK_GE( m_board->m_CopperItemRTreeCache->QueryColliding(
298 track, F_Cu, F_Cu,
299 [&]( BOARD_ITEM* other ) -> bool
300 {
301 return other == graphic;
302 },
303 nullptr, m_board->m_DRCMaxClearance ),
304 1 );
305
306 BOOST_CHECK_NE( graphic->GetNetCode(), track->GetNetCode() );
307
308 if( violationCount < 1 )
309 {
310 wxString codes;
311
312 for( int code : violationCodes )
313 codes += wxString::Format( wxT( " %d" ), code );
314
315 BOOST_TEST_MESSAGE( wxString::Format( wxT( "Reported violation codes:%s" ), codes ) );
316 }
317
318 BOOST_CHECK_GE( violationCount, 1 );
319}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
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:84
SEVERITY GetSeverity() const
Definition drc_rule.h:221
const MINOPTMAX< int > & GetValue() const
Definition drc_rule.h:200
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:184
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
void SetStartEndingLength(int aLength)
Definition eda_shape.h:190
void SetStartEndingWidth(int aWidth)
Definition eda_shape.h:192
void SetPosition(const VECTOR2I &aPos) override
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from 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:133
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:89
void SetStart(const VECTOR2I &aStart)
Definition pcb_track.h:92
const VECTOR2I & GetStart() const
Definition pcb_track.h:93
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:86
@ DRCE_SILK_MASK_CLEARANCE
Definition drc_item.h:100
@ DRCE_MIRRORED_TEXT_ON_FRONT_LAYER
Definition drc_item.h:116
@ DRCE_LIB_FOOTPRINT_ISSUES
Definition drc_item.h:85
@ DRCE_STARVED_THERMAL
Definition drc_item.h:47
@ DRCE_CLEARANCE
Definition drc_item.h:41
@ DRCE_ISOLATED_COPPER
Definition drc_item.h:46
@ DRCE_COPPER_SLIVER
Definition drc_item.h:96
@ DRCE_SHORTING_ITEMS
Definition drc_item.h:38
@ DRCE_LAST
Definition drc_item.h:131
@ DRCE_LIB_FOOTPRINT_MISMATCH
Definition drc_item.h:86
@ DRCE_UNMIRRORED_TEXT_ON_BACK_LAYER
Definition drc_item.h:117
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:51
@ 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:683