KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_footprint_realignment.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
25#include <boost/test/data/test_case.hpp>
26
27#include <optional>
28#include <string>
29#include <utility>
30#include <vector>
31
32#include <footprint_utils.h>
33
34#include <footprint.h>
35#include <pad.h>
36
37
39{
40 std::string m_TestName;
41 const std::vector<std::pair<std::string, VECTOR2I>>& m_OrigPadPositions;
42 const std::vector<std::pair<std::string, VECTOR2I>>& m_NewPadPositions;
43 std::optional<VECTOR2I> m_ExpectedPosShift;
44 std::optional<EDA_ANGLE> m_ExpectedAngleShift;
45
46 // Alls a data test case to print the name
47 friend std::ostream& operator<<( std::ostream& os, const FP_ALIGNMENT_TEST_CASE& testCase )
48 {
49 return os << testCase.m_TestName;
50 }
51};
52
53
55{
58
59 std::unique_ptr<FOOTPRINT> CreateFootprint( const std::vector<std::pair<std::string, VECTOR2I>>& padPositions )
60 {
61 std::unique_ptr<FOOTPRINT> fp = std::make_unique<FOOTPRINT>( nullptr );
62
63 for( const auto& [number, pos] : padPositions )
64 {
65 PAD* pad = new PAD( fp.get() );
66 pad->SetNumber( number );
67 pad->SetFPRelativePosition( pos );
68 fp->Add( pad );
69 }
70
71 return fp;
72 }
73
74
76 {
77 const std::unique_ptr<FOOTPRINT> fpOrig = CreateFootprint( testCase.m_OrigPadPositions );
78 const std::unique_ptr<FOOTPRINT> fpNew = CreateFootprint( testCase.m_NewPadPositions );
79
80 bool ok = ComputeFootprintShift( *fpOrig, *fpNew, m_PosShift, m_AngleShift );
81
82 if( testCase.m_ExpectedPosShift.has_value() && testCase.m_ExpectedAngleShift.has_value() )
83 {
84 BOOST_REQUIRE( ok );
85 BOOST_TEST( m_PosShift == testCase.m_ExpectedPosShift.value() );
86 BOOST_TEST( m_AngleShift == testCase.m_ExpectedAngleShift.value() );
87 }
88 else
89 {
90 BOOST_REQUIRE( !ok );
91 }
92
93 // Check that when the original footprint is rotated, we compute the same
94 // transform, but:
95 // - the move vector is rotated by the same angle
96 // - the angle shift is the same
97
98 fpOrig->SetOrientation( ANGLE_45 );
99
100 bool ok2 = ComputeFootprintShift( *fpOrig, *fpNew, m_PosShift, m_AngleShift );
101 if( testCase.m_ExpectedPosShift.has_value() && testCase.m_ExpectedAngleShift.has_value() )
102 {
103 VECTOR2I expectedPosShift = testCase.m_ExpectedPosShift.value();
104 RotatePoint( expectedPosShift, ANGLE_45 );
105
106 BOOST_REQUIRE( ok2 );
107 BOOST_TEST( m_PosShift == expectedPosShift );
108 BOOST_TEST( m_AngleShift == testCase.m_ExpectedAngleShift.value() );
109 }
110 else
111 {
112 BOOST_REQUIRE( !ok2 );
113 }
114 }
115};
116
117
118static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_NoPins{
119};
120
121
122static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_OrigPin1{
123 { "1", { 0, 0 } },
124 { "2", { 0, 1000 } },
125 { "3", { 2000, 0 } },
126 { "4", { 2000, 1000 } },
127};
128
129
130static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_OrigBodyCenter{
131 { "1", { -1000, -500 } },
132 { "2", { -1000, 500 } },
133 { "3", { 1000, -500 } },
134 { "4", { 1000, 500 } },
135};
136
137
138// Pin 1 bottom left = Level B style
139// Rotated 90 degrees CCW around origin
140static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_Rotated90DegCCW{
141 { "1", { 0, 0 } },
142 { "2", { 1000, 0 } },
143 { "3", { 1000, -2000 } },
144 { "4", { 0, -2000 } },
145};
146
147
148static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_OrigBodyCenter_Rotated90DegCCW{
149 { "1", { -500, 1000 } },
150 { "2", { 500, 1000 } },
151 { "3", { 500, -1000 } },
152 { "4", { -500, -1000 } },
153};
154
155
156static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_Pin4Deleted{
157 { "1", { 0, 0 } },
158 { "2", { 0, 1000 } },
159 { "3", { 2000, 0 } },
160};
161
162
163static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_Pin4Moved{
164 { "1", { 0, 0 } },
165 { "2", { 0, 1000 } },
166 { "3", { 2000, 0 } },
167 { "4", { 2100, 1000 } },
168};
169
170
171static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_Widened{
172 { "1", { 0, 0 } },
173 { "2", { 0, 1000 } },
174 { "3", { 2400, 0 } },
175 { "4", { 2400, 1000 } },
176};
177
178
179static const std::vector<std::pair<std::string, VECTOR2I>> FpDef_DIP4_WithMPs{
180 { "1", { 0, 0 } },
181 { "2", { 0, 1000 } },
182 { "3", { 2000, 0 } },
183 { "4", { 2000, 1000 } },
184 { "MP", { -1000, 500 } },
185 { "MP", { 3000, 500 } },
186};
187
188
189static const std::vector<FP_ALIGNMENT_TEST_CASE> FpAlignmentTestCases = {
190 {
191 "No pins",
194 std::nullopt,
195 std::nullopt,
196 },
197 {
198 "Origin point change",
201 VECTOR2I( 1000, 500 ),
202 ANGLE_0,
203 },
204 {
205 "Rotation",
208 VECTOR2I( 0, 0 ),
209 ANGLE_270,
210 },
211 {
212 "Rotation and origin point change",
215 VECTOR2I( 1000, 500 ),
216 ANGLE_270,
217 },
218 {
219 "Pin deleted",
222 VECTOR2I( 0, 0 ),
223 ANGLE_0,
224 },
225 {
226 "Pin moved",
229 VECTOR2I( 0, 0 ),
230 ANGLE_0,
231 },
232 {
233 "Footprint widened (all pins moved)",
236 VECTOR2I( -200, 0 ),
237 ANGLE_0,
238 },
239 {
240 "Ignore same named pads",
243 VECTOR2I( 0, 0 ),
244 ANGLE_0,
245 }
246};
247
248
249BOOST_FIXTURE_TEST_SUITE( FootprintRealignment, FP_REALIGNMENT_TEST_FIXTURE )
250
251
253 boost::unit_test::data::make( FpAlignmentTestCases ),
254 testCase )
255{
256 ExecuteTestCase( testCase );
257}
258
Definition pad.h:55
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
bool ComputeFootprintShift(const FOOTPRINT &aExisting, const FOOTPRINT &aNew, VECTOR2I &aShift, EDA_ANGLE &aAngleShift)
Compute position and angle shift between two footprints.
Collection of reusable/testable functions for footprint manipulation.
std::optional< EDA_ANGLE > m_ExpectedAngleShift
std::optional< VECTOR2I > m_ExpectedPosShift
friend std::ostream & operator<<(std::ostream &os, const FP_ALIGNMENT_TEST_CASE &testCase)
const std::vector< std::pair< std::string, VECTOR2I > > & m_OrigPadPositions
const std::vector< std::pair< std::string, VECTOR2I > > & m_NewPadPositions
void ExecuteTestCase(const FP_ALIGNMENT_TEST_CASE &testCase)
std::unique_ptr< FOOTPRINT > CreateFootprint(const std::vector< std::pair< std::string, VECTOR2I > > &padPositions)
BOOST_DATA_TEST_CASE(ConvertToKicadUnit, boost::unit_test::data::make(altium_to_kicad_unit), input_value, expected_result)
Test conversation from Altium internal units into KiCad internal units.
static const std::vector< FP_ALIGNMENT_TEST_CASE > FpAlignmentTestCases
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_Widened
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_OrigBodyCenter_Rotated90DegCCW
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_Rotated90DegCCW
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_Pin4Deleted
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_OrigBodyCenter
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_Pin4Moved
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_NoPins
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_OrigPin1
static const std::vector< std::pair< std::string, VECTOR2I > > FpDef_DIP4_WithMPs
BOOST_TEST(contains==c.ExpectedContains)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_AUTO_TEST_SUITE_END()
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:229
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687