KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_kicad_sexpr.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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <filesystem>
25#include <fstream>
26#include <memory>
27#include <sstream>
28#include <string>
29
33
35#include <richio.h>
36
37#include <board.h>
41#include <footprint.h>
42#include <netinfo.h>
43#include <pad.h>
44#include <pcb_shape.h>
45#include <zone.h>
46
47
54
55
59BOOST_FIXTURE_TEST_SUITE( KiCadSexprIO, KICAD_SEXPR_FIXTURE )
60
61
62
65BOOST_AUTO_TEST_CASE( Issue19775_ZoneLayerWildcards )
66{
67 std::string dataPath = KI_TEST::GetPcbnewTestDataDir() + "plugins/kicad_sexpr/Issue19775_ZoneLayers/";
68
69 BOOST_TEST_CONTEXT( "Zone layers with wildcards" )
70 {
71 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
72
73 kicadPlugin.LoadBoard( dataPath + "LayerWildcard.kicad_pcb", testBoard.get() );
74
75 // One zone in the file
76 BOOST_CHECK( testBoard->Zones().size() == 1 );
77
78 ZONE* z = testBoard->Zones()[0];
79
80 // On both front and back layers, with zone fill on both
81 BOOST_CHECK( z->GetLayerSet().Contains( F_Cu ) && z->GetLayerSet().Contains( B_Cu ) );
82 BOOST_CHECK( z->GetFilledPolysList( F_Cu )->TotalVertices() > 0 );
83 BOOST_CHECK( z->GetFilledPolysList( B_Cu )->TotalVertices() > 0 );
84 }
85
86 BOOST_TEST_CONTEXT( "Round trip layers" )
87 {
88 auto tmpBoard = std::filesystem::temp_directory_path() / "Issue19775_RoundTrip.kicad_pcb";
89
90 // Load and save the board from above to test how we write the zones into it
91 {
92 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
93 kicadPlugin.LoadBoard( dataPath + "LayerEnumerate.kicad_pcb", testBoard.get() );
94 kicadPlugin.SaveBoard( tmpBoard.string(), testBoard.get() );
95 }
96
97 // Read the new board
98 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
99 kicadPlugin.LoadBoard( tmpBoard.string(), testBoard.get() );
100
101 // One zone in the file
102 BOOST_CHECK( testBoard->Zones().size() == 1 );
103
104 ZONE* z = testBoard->Zones()[0];
105
106 // On both front and back layers, with zone fill on both
107 BOOST_CHECK( z->GetLayerSet().Contains( F_Cu ) && z->GetLayerSet().Contains( B_Cu ) );
108 BOOST_CHECK( z->GetFilledPolysList( F_Cu )->TotalVertices() > 0 );
109 BOOST_CHECK( z->GetFilledPolysList( B_Cu )->TotalVertices() > 0 );
110 BOOST_CHECK( z->LayerProperties().contains( F_Cu ) );
111 }
112}
113
114
122BOOST_AUTO_TEST_CASE( Issue23125_EmptyZoneDiscarded )
123{
124 std::string dataPath = KI_TEST::GetPcbnewTestDataDir()
125 + "plugins/kicad_sexpr/Issue23125_EmptyZone/";
126
127 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
128
129 kicadPlugin.LoadBoard( dataPath + "EmptyZone.kicad_pcb", testBoard.get() );
130
131 // The file contains 3 zones: 1 valid (with polygon) and 2 empty (no polygon).
132 // The 2 empty zones should have been discarded during loading.
133 BOOST_CHECK_EQUAL( testBoard->Zones().size(), 1 );
134
135 // The surviving zone should have a valid position
136 ZONE* z = testBoard->Zones()[0];
137 BOOST_CHECK_NO_THROW( z->GetPosition() );
138 BOOST_CHECK( z->GetNumCorners() > 0 );
139}
140
141
147BOOST_AUTO_TEST_CASE( ScientificNotationLoading )
148{
149 std::string dataPath = KI_TEST::GetPcbnewTestDataDir()
150 + "plugins/kicad_sexpr/";
151
152 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
153
154 kicadPlugin.LoadBoard( dataPath + "ScientificNotation.kicad_pcb", testBoard.get() );
155
156 // The file contains 1 arc with scientific notation in its coordinates
157 BOOST_CHECK_EQUAL( testBoard->Drawings().size(), 1 );
158
159 PCB_SHAPE* arc = dynamic_cast<PCB_SHAPE*>( testBoard->Drawings().front() );
160
161 // The arc's midpoint should be located at (4.17, -4.5e-05) in file units
162 BOOST_REQUIRE( arc );
163 BOOST_TEST( arc->GetArcMid().x == 4170000 );
164 BOOST_TEST( arc->GetArcMid().y == -45 );
165}
166
167
174BOOST_AUTO_TEST_CASE( Issue23625_CorruptedStackupCapped )
175{
176 std::string dataPath = KI_TEST::GetPcbnewTestDataDir()
177 + "plugins/kicad_sexpr/Issue23625_CorruptedStackup/";
178
179 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
180
181 BOOST_CHECK_NO_THROW( kicadPlugin.LoadBoard( dataPath + "corrupted_stackup.kicad_pcb",
182 testBoard.get() ) );
183
184 const BOARD_STACKUP& stackup =
185 testBoard->GetDesignSettings().GetStackupDescriptor();
186
187 // The test file has 200 dielectric layers (plus copper, silk, mask), well
188 // beyond the parser's 128-item cap. After loading, the count must be
189 // clamped and the board must still be usable.
190 BOOST_CHECK_LE( stackup.GetCount(), 128 );
191 BOOST_CHECK_GT( stackup.GetCount(), 0 );
192}
193
194
201BOOST_AUTO_TEST_CASE( Issue23752_AppendBoardPreservesStackupAndGrowsToSixCopperLayers )
202{
203 std::string dataPath = KI_TEST::GetPcbnewTestDataDir();
204
205 // four layer board
206 std::string destinationPath = dataPath + "issue3812.kicad_pcb";
207 // six layer board
208 std::string sourcePath = dataPath + "issue18142.kicad_pcb";
209 std::map<std::string, UTF8> props;
210
211 // basically, make sure that we start with a four layer board, append a six layer
212 // board like this is a design block apply-layout with six layers, and make
213 // sure we end up with a six layer board and a six layer stackup and not a
214 // ten layer board
215 //
216 // we also need to test the stackup properties are preserved, because the increase
217 // in copper layers should cause a stackup growth from from four to six layers,
218 // but not replace the stackup with the source board's stackup, which has different properties (e.g. finish type)
220
221 auto countCopperLayers = []( const BOARD_STACKUP& aStackup )
222 {
223 int copperLayerCount = 0;
224
225 for( BOARD_STACKUP_ITEM* item : aStackup.GetList() )
226 {
227 if( item->GetType() == BS_ITEM_TYPE_COPPER )
228 ++copperLayerCount;
229 }
230
231 return copperLayerCount;
232 };
233
234 auto findFirstDielectric = []( const BOARD_STACKUP& aStackup ) -> const BOARD_STACKUP_ITEM*
235 {
236 for( BOARD_STACKUP_ITEM* item : aStackup.GetList() )
237 {
238 if( item->GetType() == BS_ITEM_TYPE_DIELECTRIC )
239 return item;
240 }
241
242 return nullptr;
243 };
244
245 std::unique_ptr<BOARD> testBoard = std::make_unique<BOARD>();
246
247 kicadPlugin.LoadBoard( destinationPath, testBoard.get() );
248
249 const BOARD_STACKUP& initialStackup = testBoard->GetDesignSettings().GetStackupDescriptor();
250 const BOARD_STACKUP_ITEM* initialFirstDielectric = findFirstDielectric( initialStackup );
251 const int initialCopperLayerCount = testBoard->GetCopperLayerCount();
252 const LSET initialEnabledLayers = testBoard->GetEnabledLayers();
253 const wxString initialFinishType = initialStackup.m_FinishType;
254
255 BOOST_REQUIRE_EQUAL( initialCopperLayerCount, 4 );
256 BOOST_REQUIRE_EQUAL( countCopperLayers( initialStackup ), 4 );
257 BOOST_REQUIRE( initialFirstDielectric );
258 BOOST_REQUIRE_EQUAL( initialFinishType, wxS( "ENIG" ) );
259 const wxString initialFirstDielectricMaterial = initialFirstDielectric->GetMaterial();
260 const int initialFirstDielectricThickness = initialFirstDielectric->GetThickness();
261
262 kicadPlugin.LoadBoard( sourcePath, testBoard.get(), &props );
263
264 const int appendedCopperLayerCount = testBoard->GetCopperLayerCount();
265
266 if( appendedCopperLayerCount > initialCopperLayerCount )
267 testBoard->SetCopperLayerCount( appendedCopperLayerCount );
268
269 LSET enabledLayers = testBoard->GetEnabledLayers();
270 enabledLayers |= initialEnabledLayers;
271 testBoard->SetEnabledLayers( enabledLayers );
272 testBoard->GetDesignSettings().GetStackupDescriptor().SynchronizeWithBoard( &testBoard->GetDesignSettings() );
273
274 const BOARD_STACKUP& finalStackup = testBoard->GetDesignSettings().GetStackupDescriptor();
275 const BOARD_STACKUP_ITEM* finalFirstDielectric = findFirstDielectric( finalStackup );
276
277 BOOST_CHECK_EQUAL( testBoard->GetCopperLayerCount(), 6 );
278 BOOST_CHECK_EQUAL( countCopperLayers( finalStackup ), 6 );
279 BOOST_REQUIRE( finalFirstDielectric );
280 BOOST_CHECK_EQUAL( finalStackup.m_FinishType, initialFinishType );
281 BOOST_CHECK_EQUAL( finalFirstDielectric->GetMaterial(), initialFirstDielectricMaterial );
282 BOOST_CHECK_EQUAL( finalFirstDielectric->GetThickness(), initialFirstDielectricThickness );
283}
284
285
303BOOST_AUTO_TEST_CASE( FootprintSave_OmitsNetsOnAllBoardConnectedItems )
304{
305 auto tmpLib = std::filesystem::temp_directory_path() / "qa_fp_save_netinfo.pretty";
306 std::filesystem::remove_all( tmpLib );
307 std::filesystem::create_directories( tmpLib );
308
309 std::unique_ptr<BOARD> board = std::make_unique<BOARD>();
310
311 NETINFO_ITEM* net = new NETINFO_ITEM( board.get(), wxT( "TestNet" ), 1 );
312 board->Add( net );
313
314 FOOTPRINT* fp = new FOOTPRINT( board.get() );
315 board->Add( fp );
316 fp->SetFPID( LIB_ID( wxT( "scratch" ), wxT( "test_fp_save_netinfo" ) ) );
317
318 PAD* pad = new PAD( fp );
320 pad->SetSize( PADSTACK::ALL_LAYERS,
321 VECTOR2I( pcbIUScale.mmToIU( 1 ), pcbIUScale.mmToIU( 1 ) ) );
322 pad->SetNet( net );
323 fp->Add( pad );
324
325 PCB_SHAPE* shape = new PCB_SHAPE( fp, SHAPE_T::SEGMENT );
326 shape->SetLayer( F_Cu );
327 shape->SetStart( VECTOR2I( 0, 0 ) );
328 shape->SetEnd( VECTOR2I( pcbIUScale.mmToIU( 5 ), 0 ) );
329 shape->SetNet( net );
330 fp->Add( shape );
331
332 ZONE* zone = new ZONE( fp );
333 zone->SetLayer( F_Cu );
334 zone->SetNet( net );
335 fp->Add( zone );
336
337 BOOST_REQUIRE_EQUAL( pad->GetNet(), net );
338 BOOST_REQUIRE_EQUAL( shape->GetNet(), net );
339 BOOST_REQUIRE_EQUAL( zone->GetNet(), net );
340
341 // Save into the scratch library via the public library-save API. Must not throw.
342 BOOST_REQUIRE_NO_THROW( kicadPlugin.FootprintSave( tmpLib.string(), fp ) );
343
344 auto savedFile = tmpLib / "test_fp_save_netinfo.kicad_mod";
345 BOOST_REQUIRE( std::filesystem::exists( savedFile ) );
346
347 std::ifstream in( savedFile );
348 BOOST_REQUIRE_MESSAGE( in.is_open(),
349 "Failed to open serialized footprint: " << savedFile.string() );
350
351 std::stringstream ss;
352 ss << in.rdbuf();
353 BOOST_REQUIRE( !in.bad() );
354
355 const std::string contents = ss.str();
356 BOOST_REQUIRE( !contents.empty() );
357
358 BOOST_CHECK_MESSAGE( contents.find( "(net " ) == std::string::npos,
359 "Saved footprint library file must not contain (net ...) tokens:\n"
360 << contents );
361
362 // Verify the second defense directly on the save-path's transient state: clone the
363 // footprint, detach it from its parent board exactly as FootprintSave does, invoke
364 // ClearAllNets(), and assert every BOARD_CONNECTED_ITEM descendant is orphaned. This
365 // catches a regression where FootprintSave stops calling ClearAllNets() even if the
366 // serializer guards keep the file contents looking correct.
367 std::unique_ptr<FOOTPRINT> detached( static_cast<FOOTPRINT*>( fp->Clone() ) );
368 detached->SetParent( nullptr );
369 detached->SetParentGroup( nullptr );
370 detached->ClearAllNets();
371
372 BOARD_CONNECTED_ITEM* detachedPad = nullptr;
373 BOARD_CONNECTED_ITEM* detachedShape = nullptr;
374 BOARD_CONNECTED_ITEM* detachedZone = nullptr;
375
376 detached->RunOnChildren(
377 [&]( BOARD_ITEM* aItem )
378 {
379 switch( aItem->Type() )
380 {
381 case PCB_PAD_T: detachedPad = static_cast<BOARD_CONNECTED_ITEM*>( aItem ); break;
382 case PCB_SHAPE_T: detachedShape = static_cast<BOARD_CONNECTED_ITEM*>( aItem ); break;
383 case PCB_ZONE_T: detachedZone = static_cast<BOARD_CONNECTED_ITEM*>( aItem ); break;
384 default: break;
385 }
386 },
388
389 BOOST_REQUIRE( detachedPad );
390 BOOST_REQUIRE( detachedShape );
391 BOOST_REQUIRE( detachedZone );
395
396 std::filesystem::remove_all( tmpLib );
397}
398
399
408BOOST_AUTO_TEST_CASE( CopperThievingZone_RoundTrip )
409{
410 std::unique_ptr<BOARD> writeBoard = std::make_unique<BOARD>();
411
412 ZONE* zone = new ZONE( writeBoard.get() );
413 zone->SetLayer( F_Cu );
414 zone->AppendCorner( VECTOR2I( 0, 0 ), -1 );
415 zone->AppendCorner( VECTOR2I( pcbIUScale.mmToIU( 10 ), 0 ), -1 );
416 zone->AppendCorner( VECTOR2I( pcbIUScale.mmToIU( 10 ), pcbIUScale.mmToIU( 10 ) ), -1 );
417 zone->AppendCorner( VECTOR2I( 0, pcbIUScale.mmToIU( 10 ) ), -1 );
419
420 THIEVING_SETTINGS thieving;
422 thieving.element_size = pcbIUScale.mmToIU( 0.42 );
423 thieving.gap = pcbIUScale.mmToIU( 1.27 );
424 thieving.line_width = pcbIUScale.mmToIU( 0.35 );
425 thieving.stagger = true;
426 thieving.orientation = EDA_ANGLE( 30.0, DEGREES_T );
427 zone->SetThievingSettings( thieving );
428
429 writeBoard->Add( zone );
430
431 std::filesystem::path tmpPath = std::filesystem::temp_directory_path()
432 / "copper_thieving_roundtrip.kicad_pcb";
433
434 PCB_IO_KICAD_SEXPR writer;
435 writer.SaveBoard( tmpPath.string(), writeBoard.get() );
436
437 std::unique_ptr<BOARD> readBoard = std::make_unique<BOARD>();
438 PCB_IO_KICAD_SEXPR reader;
439 reader.LoadBoard( tmpPath.string(), readBoard.get() );
440
441 BOOST_REQUIRE_EQUAL( readBoard->Zones().size(), 1u );
442
443 ZONE* loaded = readBoard->Zones()[0];
444
445 BOOST_CHECK( loaded->GetFillMode() == ZONE_FILL_MODE::COPPER_THIEVING );
446 BOOST_CHECK( loaded->IsCopperThieving() );
447 BOOST_CHECK_EQUAL( loaded->GetNetCode(), 0 );
448
449 const THIEVING_SETTINGS& loadedSettings = loaded->GetThievingSettings();
450 BOOST_CHECK( loadedSettings.pattern == THIEVING_PATTERN::HATCH );
451 BOOST_CHECK_EQUAL( loadedSettings.element_size, thieving.element_size );
452 BOOST_CHECK_EQUAL( loadedSettings.gap, thieving.gap );
453 BOOST_CHECK_EQUAL( loadedSettings.line_width, thieving.line_width );
454 BOOST_CHECK_EQUAL( loadedSettings.stagger, true );
455 BOOST_CHECK( loadedSettings.orientation == EDA_ANGLE( 30.0, DEGREES_T ) );
456
457 std::filesystem::remove( tmpPath );
458}
459
460
465BOOST_AUTO_TEST_CASE( CopperThievingZone_AllPatternsRoundTrip )
466{
467 const std::array<THIEVING_PATTERN, 3> patterns = {
471 };
472
473 for( THIEVING_PATTERN pattern : patterns )
474 {
475 BOOST_TEST_CONTEXT( "pattern enum value " << static_cast<int>( pattern ) )
476 {
477 std::unique_ptr<BOARD> writeBoard = std::make_unique<BOARD>();
478
479 ZONE* zone = new ZONE( writeBoard.get() );
480 zone->SetLayer( F_Cu );
481 zone->AppendCorner( VECTOR2I( 0, 0 ), -1 );
482 zone->AppendCorner( VECTOR2I( pcbIUScale.mmToIU( 5 ), 0 ), -1 );
483 zone->AppendCorner( VECTOR2I( pcbIUScale.mmToIU( 5 ), pcbIUScale.mmToIU( 5 ) ), -1 );
484 zone->AppendCorner( VECTOR2I( 0, pcbIUScale.mmToIU( 5 ) ), -1 );
486
487 THIEVING_SETTINGS thieving = zone->GetThievingSettings();
488 thieving.pattern = pattern;
489 zone->SetThievingSettings( thieving );
490
491 writeBoard->Add( zone );
492
493 std::filesystem::path tmpPath = std::filesystem::temp_directory_path()
494 / "copper_thieving_pattern.kicad_pcb";
495 PCB_IO_KICAD_SEXPR writer;
496 writer.SaveBoard( tmpPath.string(), writeBoard.get() );
497
498 std::unique_ptr<BOARD> readBoard = std::make_unique<BOARD>();
499 PCB_IO_KICAD_SEXPR reader;
500 reader.LoadBoard( tmpPath.string(), readBoard.get() );
501
502 BOOST_REQUIRE_EQUAL( readBoard->Zones().size(), 1u );
503 BOOST_CHECK( readBoard->Zones()[0]->GetThievingSettings().pattern == pattern );
504
505 std::filesystem::remove( tmpPath );
506 }
507 }
508}
509
510
517BOOST_AUTO_TEST_CASE( CopperThievingZone_RejectedInOldFileVersion )
518{
519 std::filesystem::path tmpPath = std::filesystem::temp_directory_path()
520 / "copper_thieving_old_version.kicad_pcb";
521 std::ofstream out( tmpPath );
522 // 20260512 is the Net Chains release; thieving needs >= 20260513. Using the
523 // immediately-prior version exercises the boundary check.
524 out << "(kicad_pcb (version 20260512) (generator \"test\") (generator_version \"test\")"
525 << " (general (thickness 1.6)) (paper \"A4\")"
526 << " (layers (0 \"F.Cu\" signal) (31 \"B.Cu\" signal))"
527 << " (zone (net 0) (net_name \"\") (layer \"F.Cu\") (uuid \"00000000-0000-0000-0000-000000000001\")"
528 << " (hatch edge 0.5)"
529 << " (connect_pads (clearance 0))"
530 << " (min_thickness 0.25) (filled_areas_thickness no)"
531 << " (fill yes (mode thieving) (thermal_gap 0.5) (thermal_bridge_width 0.5)"
532 << " (island_removal_mode 0))"
533 << " (polygon (pts (xy 0 0) (xy 5 0) (xy 5 5) (xy 0 5))))"
534 << ")";
535 out.close();
536
537 std::unique_ptr<BOARD> readBoard = std::make_unique<BOARD>();
538 PCB_IO_KICAD_SEXPR reader;
539 BOOST_CHECK_THROW( reader.LoadBoard( tmpPath.string(), readBoard.get() ), IO_ERROR );
540
541 std::filesystem::remove( tmpPath );
542}
543
544
551BOOST_AUTO_TEST_CASE( CopperThievingZone_RejectsMalformedGeometry )
552{
553 std::filesystem::path tmpPath = std::filesystem::temp_directory_path()
554 / "copper_thieving_malformed.kicad_pcb";
555 std::ofstream out( tmpPath );
556 out << "(kicad_pcb (version 20260513) (generator \"test\") (generator_version \"test\")"
557 << " (general (thickness 1.6)) (paper \"A4\")"
558 << " (layers (0 \"F.Cu\" signal) (31 \"B.Cu\" signal))"
559 << " (zone (net 0) (net_name \"\") (layer \"F.Cu\") (uuid \"00000000-0000-0000-0000-000000000002\")"
560 << " (hatch edge 0.5)"
561 << " (connect_pads (clearance 0))"
562 << " (min_thickness 0.25) (filled_areas_thickness no)"
563 << " (fill yes (mode thieving)"
564 << " (thermal_gap 0.5) (thermal_bridge_width 0.5)"
565 << " (island_removal_mode 0)"
566 << " (thieving (type dots) (size -1) (gap 0)"
567 << " (width -5) (stagger no) (orientation 0)))"
568 << " (polygon (pts (xy 0 0) (xy 5 0) (xy 5 5) (xy 0 5))))"
569 << ")";
570 out.close();
571
572 std::unique_ptr<BOARD> readBoard = std::make_unique<BOARD>();
573 PCB_IO_KICAD_SEXPR reader;
574 reader.LoadBoard( tmpPath.string(), readBoard.get() );
575
576 BOOST_REQUIRE_EQUAL( readBoard->Zones().size(), 1u );
577
578 const THIEVING_SETTINGS& loaded = readBoard->Zones()[0]->GetThievingSettings();
579 BOOST_CHECK_GT( loaded.element_size, 0 );
580 BOOST_CHECK_GT( loaded.gap, 0 );
581 BOOST_CHECK_GT( loaded.line_width, 0 );
582
583 std::filesystem::remove( tmpPath );
584}
585
586
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:125
General utilities for PCB file IO for QA programs.
@ BS_ITEM_TYPE_COPPER
@ BS_ITEM_TYPE_DIELECTRIC
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual void SetNet(NETINFO_ITEM *aNetInfo)
Set a NET_INFO object for the item.
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
Manage one layer needed to make a physical board.
int GetThickness(int aDielectricSubLayer=0) const
wxString GetMaterial(int aDielectricSubLayer=0) const
Manage layers needed to make a physical board.
int GetCount() const
wxString m_FinishType
The name of external copper finish.
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:198
void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:240
VECTOR2I GetArcMid() const
void SetFPID(const LIB_ID &aFPID)
Definition footprint.h:430
EDA_ITEM * Clone() const override
Invoke a function on all children.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
A logical library item identifier and consists of various portions much like a URI.
Definition lib_id.h:49
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
Definition lset.h:63
Handle the data for a net.
Definition netinfo.h:50
static NETINFO_ITEM * OrphanedItem()
NETINFO_ITEM meaning that there was no net assigned for an item, as there was no board storing net li...
Definition netinfo.h:267
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
Definition padstack.h:177
Definition pad.h:55
A #PLUGIN derivation for saving and loading Pcbnew s-expression formatted files.
BOARD * LoadBoard(const wxString &aFileName, BOARD *aAppendToMe, const std::map< std::string, UTF8 > *aProperties=nullptr, PROJECT *aProject=nullptr) override
Load information from some input file format that this PCB_IO implementation knows about into either ...
void SaveBoard(const wxString &aFileName, BOARD *aBoard, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Write aBoard to a storage file in a format that this PCB_IO implementation knows about or it can be u...
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
int TotalVertices() const
Return total number of vertices stored in the set.
Handle a list of polygons defining a copper zone.
Definition zone.h:74
const THIEVING_SETTINGS & GetThievingSettings() const
Definition zone.h:355
ZONE_LAYER_PROPERTIES & LayerProperties(PCB_LAYER_ID aLayer)
Definition zone.h:150
std::shared_ptr< SHAPE_POLY_SET > GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition zone.h:688
virtual void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition zone.cpp:603
bool IsCopperThieving() const
Definition zone.h:353
void SetFillMode(ZONE_FILL_MODE aFillMode)
Definition zone.cpp:609
void SetThievingSettings(const THIEVING_SETTINGS &aSettings)
Definition zone.h:356
VECTOR2I GetPosition() const override
Definition zone.cpp:527
void SetNet(NETINFO_ITEM *aNetInfo) override
Override that drops aNetInfo when this zone is in copper-thieving fill mode.
Definition zone.cpp:594
ZONE_FILL_MODE GetFillMode() const
Definition zone.h:242
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition zone.h:137
bool AppendCorner(VECTOR2I aPosition, int aHoleIdx, bool aAllowDuplication=false)
Add a new corner to the zone outline (to the main outline or a hole)
Definition zone.cpp:1280
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition zone.h:606
@ DEGREES_T
Definition eda_angle.h:31
@ RECURSE
Definition eda_item.h:53
@ SEGMENT
Definition eda_shape.h:50
std::unique_ptr< BOARD > readBoard(wxString &aFilename)
@ B_Cu
Definition layer_ids.h:65
@ F_Cu
Definition layer_ids.h:64
std::string GetPcbnewTestDataDir()
Utility which returns a path to the data directory where the test board files are stored.
constexpr char APPEND_PRESERVE_DESTINATION_STACKUP[]
Definition pcb_io.h:47
PCB_IO_KICAD_SEXPR kicadPlugin
Parameters that drive copper-thieving fill generation.
EDA_ANGLE orientation
THIEVING_PATTERN pattern
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_TEST(contains==c.ExpectedContains)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(Issue19775_ZoneLayerWildcards)
Declares the struct as the Boost test fixture.
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_CHECK_EQUAL(result, "25.4")
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:85
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:105
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:84
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
THIEVING_PATTERN
Shape stamped onto the grid for a copper-thieving fill.