KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_ipc2581.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
20#include <filesystem>
21#include <fstream>
22#include <iterator>
23#include <map>
24#include <string>
25
27
29
30#include <board.h>
31#include <footprint.h>
32#include <pad.h>
33#include <lset.h>
34#include <base_units.h>
35#include <core/mirror.h>
36
37#include <wx/filename.h>
38
39
40BOOST_AUTO_TEST_SUITE( Ipc2581Io )
41
42
43
56BOOST_AUTO_TEST_CASE( Issue18013_FlippedFootprintRotation )
57{
58 BOARD board;
59
60 auto addFootprint =
61 [&]( const wxString& aRef, const VECTOR2I& aPos, bool aFlip ) -> FOOTPRINT*
62 {
63 FOOTPRINT* fp = new FOOTPRINT( &board );
64 fp->SetReference( aRef );
65 fp->SetPosition( aPos );
66 board.Add( fp );
67
68 PAD* pad = new PAD( fp );
69 pad->SetNumber( wxT( "1" ) );
70 pad->SetAttribute( PAD_ATTRIB::SMD );
72 pad->SetSize( PADSTACK::ALL_LAYERS,
73 VECTOR2I( pcbIUScale.mmToIU( 1.0 ), pcbIUScale.mmToIU( 1.0 ) ) );
74 pad->SetLayerSet( LSET( { F_Cu, F_Mask } ) );
75 fp->Add( pad );
76
77 // Flip first, then set the absolute board orientation so GetOrientation()
78 // is deterministic regardless of any rotation the flip itself applies.
79 if( aFlip )
81
82 fp->SetOrientationDegrees( 30 );
83
84 return fp;
85 };
86
87 FOOTPRINT* flipped = addFootprint( wxT( "U1" ),
88 VECTOR2I( pcbIUScale.mmToIU( 50 ), pcbIUScale.mmToIU( 50 ) ),
89 true );
90 FOOTPRINT* top = addFootprint( wxT( "U2" ),
91 VECTOR2I( pcbIUScale.mmToIU( 60 ), pcbIUScale.mmToIU( 60 ) ),
92 false );
93
94 BOOST_REQUIRE( flipped->IsFlipped() );
95 BOOST_REQUIRE( !top->IsFlipped() );
96
97 PCB_IO_IPC2581 ipc2581Plugin;
98
99 wxString tempPath = wxFileName::CreateTempFileName( wxT( "kicad_ipc2581_test" ) );
100
101 std::map<std::string, UTF8> props;
102 props["units"] = "mm";
103 props["version"] = "C";
104 props["sigfig"] = "3";
105
106 BOOST_REQUIRE_NO_THROW( ipc2581Plugin.SaveBoard( tempPath, &board, &props ) );
107 BOOST_REQUIRE( wxFileExists( tempPath ) );
108
109 std::ifstream xmlFile( tempPath.ToStdString() );
110 BOOST_REQUIRE( xmlFile.is_open() );
111
112 std::string xml( ( std::istreambuf_iterator<char>( xmlFile ) ),
113 std::istreambuf_iterator<char>() );
114 xmlFile.close();
115
116 // Return the <Component>...</Component> block for a given refDes so the checks below
117 // cannot bleed across into a sibling component.
118 auto componentRegion =
119 [&]( const std::string& aRef ) -> std::string
120 {
121 size_t start = xml.find( "refDes=\"" + aRef + "\"" );
122
123 if( start == std::string::npos )
124 return std::string();
125
126 size_t end = xml.find( "</Component>", start );
127
128 return xml.substr( start, end == std::string::npos ? std::string::npos
129 : end - start );
130 };
131
132 std::string u1 = componentRegion( "U1" );
133 BOOST_REQUIRE_MESSAGE( !u1.empty(), "Flipped component U1 should be exported" );
134
135 BOOST_CHECK_MESSAGE( u1.find( "mirror=\"true\"" ) != std::string::npos,
136 "Flipped component must carry mirror=\"true\". Region: " + u1 );
137 BOOST_CHECK_MESSAGE( u1.find( "rotation=\"150.0\"" ) != std::string::npos,
138 "Flipped 30 degree component must export rotation=\"150.0\". Region: "
139 + u1 );
140
141 // Guard against the two known incorrect formulas so the test fails on regression.
142 BOOST_CHECK_MESSAGE( u1.find( "rotation=\"330.0\"" ) == std::string::npos,
143 "Flipped rotation must not be a bare Invert() (330.0). Region: " + u1 );
144 BOOST_CHECK_MESSAGE( u1.find( "rotation=\"30.0\"" ) == std::string::npos,
145 "Flipped rotation must not be the unadjusted orientation (30.0). Region: "
146 + u1 );
147
148 std::string u2 = componentRegion( "U2" );
149 BOOST_REQUIRE_MESSAGE( !u2.empty(), "Top component U2 should be exported" );
150
151 BOOST_CHECK_MESSAGE( u2.find( "mirror=\"true\"" ) == std::string::npos,
152 "Top component must not be mirrored. Region: " + u2 );
153 BOOST_CHECK_MESSAGE( u2.find( "rotation=\"30.0\"" ) != std::string::npos,
154 "Top 30 degree component must export rotation=\"30.0\". Region: " + u2 );
155
156 std::filesystem::remove( std::filesystem::path( tempPath.ToStdString() ) );
157}
158
159
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
Definition board.cpp:1295
void SetPosition(const VECTOR2I &aPos) override
void SetOrientationDegrees(double aOrientation)
Definition footprint.h:432
bool IsFlipped() const
Definition footprint.h:614
void SetReference(const wxString &aReference)
Definition footprint.h:847
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT, bool aSkipConnectivity=false) override
Removes an item from the container.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
VECTOR2I GetPosition() const override
Definition footprint.h:403
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
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:61
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...
@ F_Mask
Definition layer_ids.h:93
@ F_Cu
Definition layer_ids.h:60
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
@ SMD
Smd pad, appears on the solder paste layer (default)
Definition padstack.h:99
@ RECTANGLE
Definition padstack.h:54
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
KIBIS top(path, &reporter)
BOOST_CHECK_MESSAGE(totalMismatches==0, std::to_string(totalMismatches)+" board(s) with strategy disagreements")
VECTOR2I end
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683